<script setup>
import { ref, nextTick, onMounted, onUnmounted, computed } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { Input, Button, Avatar, Spin, Empty, message, Dropdown, Menu, MenuItem, Switch, Modal } from 'ant-design-vue'
import { SendOutlined, AudioOutlined, MessageOutlined, SettingOutlined } from '@ant-design/icons-vue'
import { useAuthStore } from '@/stores/auth'
import { API_CONFIG } from '@/config/api'
import axios from 'axios'
import request from '@/api/request'
import hljs from 'highlight.js/lib/core'
import 'highlight.js/styles/github.css' // 使用GitHub风格的主题

// 导入常用语言支持
import javascript from 'highlight.js/lib/languages/javascript'
import typescript from 'highlight.js/lib/languages/typescript'
import python from 'highlight.js/lib/languages/python'
import java from 'highlight.js/lib/languages/java'
import cpp from 'highlight.js/lib/languages/cpp'
import csharp from 'highlight.js/lib/languages/csharp'
import php from 'highlight.js/lib/languages/php'
import go from 'highlight.js/lib/languages/go'
import rust from 'highlight.js/lib/languages/rust'
import sql from 'highlight.js/lib/languages/sql'
import json from 'highlight.js/lib/languages/json'
import xml from 'highlight.js/lib/languages/xml'
import css from 'highlight.js/lib/languages/css'
import bash from 'highlight.js/lib/languages/bash'

// 注册语言支持
hljs.registerLanguage('javascript', javascript)
hljs.registerLanguage('js', javascript)
hljs.registerLanguage('typescript', typescript)
hljs.registerLanguage('ts', typescript)
hljs.registerLanguage('python', python)
hljs.registerLanguage('py', python)
hljs.registerLanguage('java', java)
hljs.registerLanguage('cpp', cpp)
hljs.registerLanguage('c++', cpp)
hljs.registerLanguage('c', cpp)
hljs.registerLanguage('csharp', csharp)
hljs.registerLanguage('cs', csharp)
hljs.registerLanguage('php', php)
hljs.registerLanguage('go', go)
hljs.registerLanguage('golang', go)
hljs.registerLanguage('rust', rust)
hljs.registerLanguage('rs', rust)
hljs.registerLanguage('sql', sql)
hljs.registerLanguage('json', json)
hljs.registerLanguage('xml', xml)
hljs.registerLanguage('html', xml)
hljs.registerLanguage('css', css)
hljs.registerLanguage('bash', bash)
hljs.registerLanguage('sh', bash)
hljs.registerLanguage('shell', bash)

// 聊天状态
const messages = ref([])
const inputText = ref('')
const isTyping = ref(false)
// 强制更新计数器，用于触发Vue响应式更新
const updateCounter = ref(0)
const chatContainer = ref(null)

// API配置 - 使用统一配置，聊天接口路径
const API_BASE_URL = API_CONFIG.BASE_URL + '/api/v1/aiAgent/chat'
const isStreamMode = ref(true) // 流式输出模式
const isConnecting = ref(false) // 连接状态
const settingsVisible = ref(false) // 设置面板是否可见

// 电话模式相关状态
const isCallMode = ref(false) // 是否处于电话模式
const callState = ref('idle') // 电话状态：idle, calling, listening, thinking, speaking, ended
const callDuration = ref(0) // 通话时长（秒）
const callTimer = ref(null) // 通话计时器

// 停顿检测相关
const audioStream = ref(null) // 音频流
const audioContext = ref(null) // 音频上下文
const analyser = ref(null) // 音频分析器
const silenceTimer = ref(null) // 静音计时器
const isSpeaking = ref(false) // 是否正在说话
const silenceThreshold = ref(2000) // 静音时长阈值（毫秒）

// 语音活动检测(VAD)相关
const currentVolume = ref(0) // 当前音量 (0-1)
const baselineVolume = ref(0) // 环境基线音量
const volumeThreshold = ref(0.05) // 音量敏感度阈值
const isCalibrating = ref(false) // 是否正在校准
const calibrationSamples = ref([]) // 校准样本
const showAudioSettings = ref(false) // 是否显示音频设置
const volumeHistory = ref([]) // 音量历史记录
const sensitivity = ref(3) // 敏感度等级 (1-5)

// 对话设置
const chatSettings = ref({
	streamOutput: true, // 流式输出
	autoScroll: true, // 自动滚动
	showTimestamp: true, // 显示时间戳
})

// 认证相关
const router = useRouter()
const route = useRoute()
const authStore = useAuthStore()

// 角色ID - 从路由参数或推荐页面传入
const roleId = ref(null)

// 游客对话限制
const GUEST_MESSAGE_LIMIT = 5 // 游客对话次数限制
const guestMessageCount = ref(0) // 游客已发送消息数
const showLoginModal = ref(false) // 是否显示登录提示
const showGuestNotice = ref(true) // 是否显示游客体验公告

// 消息交互状态
const hoveredMessageId = ref(null)

// 移动端检测
const isMobile = ref(false) // 是否为移动端

// 当前对话的AI角色信息
const currentRobot = ref({
	id: 1,
	name: 'AI助手',
	avatar: 'https://lh.ithxs.com/apis.php?act=def&seed=1',
	status: '在线',
	description: '我是你的智能助手，随时为你提供帮助和支持。',
})

// 提取头像URL作为独立的计算属性，避免因status变化导致头像重新加载
const robotAvatar = computed(() => currentRobot.value.avatar)
const robotName = computed(() => currentRobot.value.name)

// 模拟聊天记录
const mockMessages = [
	{
		id: 1,
		type: 'bot',
		content: '你好！我是AI助手，很高兴与你聊天。有什么我可以帮助你的吗？',
		timestamp: '2024-01-15 10:30:25',
	},
]

// 检查游客对话限制
const checkGuestLimit = () => {
	// 如果已登录，直接返回true
	if (authStore.isAuthenticated) {
		return true
	}

	// 检查游客对话次数限制
	if (guestMessageCount.value >= GUEST_MESSAGE_LIMIT) {
		showLoginModal.value = true
		return false
	}

	return true
}

// 登录提示相关函数
const handleGoToLogin = () => {
	showLoginModal.value = false
	router.push('/login')
}

const handleGoToRegister = () => {
	showLoginModal.value = false
	router.push('/register')
}

const handleCloseLoginModal = () => {
	showLoginModal.value = false
}

// 关闭游客体验公告
const closeGuestNotice = () => {
	showGuestNotice.value = false
}

// 计算剩余对话次数
const remainingMessages = computed(() => {
	if (authStore.isAuthenticated) return null
	return Math.max(0, GUEST_MESSAGE_LIMIT - guestMessageCount.value)
})

// 发送消息
const sendMessage = async () => {
	if (!inputText.value.trim() || isConnecting.value) return

	// 检查游客对话限制
	if (!checkGuestLimit()) {
		return
	}

	const userContent = inputText.value.trim()
	const userMessage = {
		id: Date.now(),
		type: 'user',
		content: userContent,
		rawContent: userContent, // 存储原始内容
		timestamp: new Date().toLocaleString('zh-CN'),
	}

	// 添加用户消息到列表
	messages.value.push(userMessage)
	inputText.value = ''

	// 如果是游客用户，增加对话计数
	if (!authStore.isAuthenticated) {
		guestMessageCount.value++
	}

	// 滚动到底部
	await nextTick()
	if (chatSettings.value.autoScroll) {
		scrollToBottom()
	}

	try {
		// 记录请求开始时间
		const startTime = Date.now()

		// 创建AI消息占位符，显示加载状态
		const botMessage = {
			id: Date.now() + 1,
			type: 'bot',
			content: '',
			rawContent: '',
			timestamp: new Date().toLocaleString('zh-CN'),
			isLoading: true,
			startTime: startTime,
		}
		messages.value.push(botMessage)

		// 滚动到底部显示加载状态
		await nextTick()
		if (chatSettings.value.autoScroll) {
			scrollToBottom()
		}

		// 设置连接状态
		isConnecting.value = true
		isTyping.value = true

		// 根据输出模式更新AI状态
		if (chatSettings.value.streamOutput) {
			currentRobot.value.status = 'AI输入中'
		} else {
			currentRobot.value.status = 'AI思考中'
		}

		// 构建消息历史（不包含当前占位消息）
		const messageList = messages.value
			.filter(msg => !msg.isLoading)
			.map(msg => ({
				role: msg.type === 'user' ? 'user' : 'assistant',
				content: msg.content,
			}))

		const requestData = {
			messageList: messageList,
			isStream: chatSettings.value.streamOutput,
			// 如果有roleId，则添加到请求中
			...(roleId.value && { roleId: roleId.value })
		}

		console.log('发送API请求:', requestData)
		console.log('当前roleId:', roleId.value, 'ID类型:', typeof roleId.value)

		if (chatSettings.value.streamOutput) {
			await handleStreamResponse(requestData, botMessage)
		} else {
			await handleNormalResponse(requestData, botMessage)
		}
	} catch (error) {
		console.error('API调用失败:', error)

		// 添加错误消息 - 只显示用户友好的提示，不暴露技术细节
		const errorMessage = {
			id: Date.now() + 1,
			type: 'bot',
			content: '抱歉，服务器暂时无法响应，请稍后再试。',
			timestamp: new Date().toLocaleString('zh-CN'),
			isError: true,
		}
		messages.value.push(errorMessage)

		message.error('发送失败，请稍后重试')
	} finally {
		isConnecting.value = false
		isTyping.value = false
		// 确保AI状态重置为在线（除非已经在处理成功响应中重置）
		if (currentRobot.value.status !== '在线') {
			currentRobot.value.status = '在线'
		}
		await nextTick()
		if (chatSettings.value.autoScroll) {
			scrollToBottom()
		}
	}
}

// 打字机效果函数
const typewriterEffect = async (messageObj, newText) => {
	if (!newText || !chatSettings.value.streamOutput) {
		// 如果不是流式模式，直接显示
		messageObj.content += newText
		messageObj.rawContent += newText
		updateCounter.value++
		await nextTick()
		if (chatSettings.value.autoScroll) {
			scrollToBottom()
		}
		return
	}

	// 逐字符显示
	for (let i = 0; i < newText.length; i++) {
		messageObj.content += newText[i]
		messageObj.rawContent += newText[i]

		// 强制触发Vue响应式更新
		updateCounter.value++

		// 等待DOM更新
		await nextTick()

		// 自动滚动
		if (chatSettings.value.autoScroll) {
			scrollToBottom()
		}

		// 打字延迟（可以根据需要调整速度）
		if (i < newText.length - 1) {
			await new Promise(resolve => setTimeout(resolve, 8)) // 8ms延迟，更快的打字速度
		}
	}
}

// 处理流式响应
const handleStreamResponse = async (requestData, botMessage) => {
	try {
		console.log('开始处理流式请求...')
		const response = await fetch(API_BASE_URL, {
			method: 'POST',
			headers: {
				'Content-Type': 'application/json',
			},
			body: JSON.stringify(requestData),
		})

		console.log('响应状态:', response.status, response.statusText)
		console.log('响应头:', Object.fromEntries(response.headers.entries()))

		if (!response.ok) {
			throw new Error(`HTTP ${response.status}: ${response.statusText}`)
		}

		// 检查响应类型
		const contentType = response.headers.get('content-type')
		console.log('Content-Type:', contentType)

		// 对于流式请求，直接尝试按流式处理，不管content-type
		console.log('尝试按流式响应处理，忽略content-type检查...')

		// 在读取流之前先克隆响应，作为备用方案
		const clonedResponse = response.clone()

		// 设置为流式状态，但保持加载状态直到收到第一个内容
		botMessage.isStreaming = true
		// 注意：不要立即设置 isLoading = false，等收到第一个内容时再设置
		console.log('开始流式消息处理:', botMessage)

		const reader = response.body?.getReader()
		if (!reader) {
			throw new Error('无法获取响应流')
		}

		const decoder = new TextDecoder()
		let buffer = ''
		let chunkCount = 0

		// 辅助函数：安全提取AI内容
		const extractSafeContent = parsed => {
			if (!parsed || typeof parsed !== 'object') {
				return null
			}

			// 检查是否为成功响应
			if (parsed.success !== true && parsed.success !== undefined) {
				return `[错误] ${parsed.errorMsg || parsed.error || '未知错误'}`
			}

			// 提取内容
			const content = parsed.content || parsed.text || parsed.message

			// 验证内容是否安全（不包含原始数据格式）
			if (typeof content === 'string' && content.length > 0) {
				// 排除包含原始数据特征的内容
				const dangerousPatterns = ['data:', '{"success"', '"errorMsg"', '"content"']
				const isDangerous = dangerousPatterns.some(pattern => content.includes(pattern))

				if (!isDangerous) {
					return content
				}
			}

			return null
		}

		while (true) {
			const { done, value } = await reader.read()

			if (done) {
				console.log('流式响应结束，总共接收', chunkCount, '个数据块')
				break
			}

			chunkCount++
			const chunk = decoder.decode(value, { stream: true })
			console.log(`接收数据块 ${chunkCount} (${chunk.length} 字符):`, JSON.stringify(chunk.substring(0, 100)))

			buffer += chunk
			const lines = buffer.split('\n')
			buffer = lines.pop() || '' // 保存未完成的行

			for (const line of lines) {
				const trimmedLine = line.trim()
				console.log('处理行:', JSON.stringify(trimmedLine))

				if (!trimmedLine) continue

				// 处理各种格式的流式数据
				let dataStr = ''

				// 1. 处理SSE格式 (data: ...)
				if (trimmedLine.startsWith('data:')) {
					dataStr = trimmedLine.slice(5).trim()
				}
				// 2. 处理直接JSON格式
				else if (trimmedLine.startsWith('{') && trimmedLine.endsWith('}')) {
					dataStr = trimmedLine
				}
				// 3. 处理纯文本格式
				else if (!trimmedLine.includes(':') && trimmedLine.length > 0) {
					// 直接作为文本内容处理
					const currentBotMessage = messages.value[messages.value.length - 1]
					if (currentBotMessage && currentBotMessage.type === 'bot' && currentBotMessage.isStreaming) {
						// 首次接收到内容时，移除加载状态
						if (currentBotMessage.isLoading) {
							currentBotMessage.isLoading = false
							console.log('首次接收到文本内容，移除加载状态')
						}

						// 使用打字机效果显示新内容
						await typewriterEffect(currentBotMessage, trimmedLine)

						console.log('累积文本内容:', currentBotMessage.content)
					}
					continue
				}

				// 处理结束标记
				if (dataStr === '[DONE]' || dataStr === 'DONE') {
					console.log('接收到结束标记')
					break
				}

				if (dataStr) {
					try {
						const parsed = JSON.parse(dataStr)
						console.log('解析的对象:', parsed)

						const safeContent = extractSafeContent(parsed)
						console.log('安全内容:', safeContent)

						if (safeContent) {
							// 更新AI消息内容
							const currentBotMessage = messages.value[messages.value.length - 1]
							if (currentBotMessage && currentBotMessage.type === 'bot' && currentBotMessage.isStreaming) {
								// 首次接收到内容时，移除加载状态
								if (currentBotMessage.isLoading) {
									currentBotMessage.isLoading = false
									console.log('首次接收到JSON内容，移除加载状态')
								}

								// 清理被污染的内容
								if (currentBotMessage.content.includes('data:')) {
									console.log('清理被污染的消息内容')
									currentBotMessage.content = ''
									currentBotMessage.rawContent = ''
								}

								// 使用打字机效果显示新内容
								await typewriterEffect(currentBotMessage, safeContent)

								console.log('累积JSON内容:', currentBotMessage.content)
							}
						}
					} catch (e) {
						console.warn('JSON解析失败，尝试作为纯文本处理:', dataStr)
						// 如果JSON解析失败，尝试作为纯文本处理
						const currentBotMessage = messages.value[messages.value.length - 1]
						if (currentBotMessage && currentBotMessage.type === 'bot' && currentBotMessage.isStreaming) {
							// 首次接收到内容时，移除加载状态
							if (currentBotMessage.isLoading) {
								currentBotMessage.isLoading = false
							}

							// 使用打字机效果显示新内容
							await typewriterEffect(currentBotMessage, dataStr)
						}
					}
				}
			}
		}

		// 标记流式传输完成
		const finalBotMessage = messages.value[messages.value.length - 1]
		if (finalBotMessage && finalBotMessage.type === 'bot') {
			finalBotMessage.isStreaming = false
			// 计算响应时间
			if (finalBotMessage.startTime) {
				finalBotMessage.responseTime = Date.now() - finalBotMessage.startTime
				delete finalBotMessage.startTime
			}
			console.log('流式传输完成，最终内容:', finalBotMessage.content)

			// 如果没有收到任何内容，尝试用克隆的响应作为JSON处理
			if (!finalBotMessage.content.trim()) {
				console.log('流式处理未获取到内容，尝试作为普通JSON响应处理...')
				try {
					const jsonData = await clonedResponse.json()
					console.log('备用JSON响应数据:', jsonData)

					const content =
						jsonData.content || jsonData.message || jsonData.data || jsonData.text || jsonData.choices?.[0]?.message?.content || jsonData.result

					if (content) {
						finalBotMessage.content = content
						finalBotMessage.rawContent = content
						console.log('通过JSON备用方案获取到内容:', content)
					} else {
						finalBotMessage.content = '收到了回复，但内容为空。请检查API响应格式。'
						finalBotMessage.isError = true
					}
				} catch (jsonError) {
					console.error('JSON备用方案也失败:', jsonError)
					finalBotMessage.content = '无法解析服务器响应。请稍后重试。'
					finalBotMessage.isError = true
				}
			}

			// 重置AI状态为在线
			currentRobot.value.status = '在线'
		}
	} catch (error) {
		console.error('流式响应处理失败:', error)
		throw error
	}
}

// 处理普通响应
const handleNormalResponse = async (requestData, botMessage) => {
	try {
		console.log('开始处理普通响应请求...')
		const response = await axios.post(API_BASE_URL, requestData, {
			headers: {
				'Content-Type': 'application/json',
			},
			timeout: 30000, // 30秒超时
		})

		console.log('普通响应状态:', response.status)
		console.log('普通响应数据:', response.data)
		console.log('响应数据类型:', typeof response.data)

		let botContent = null

		// 检查是否是流式格式的数据（即使在非流式模式下）
		if (typeof response.data === 'string' && response.data.includes('data:')) {
			console.log('检测到流式格式数据，进行解析...')
			botContent = parseStreamLikeResponse(response.data)
		} else if (response.data && typeof response.data === 'object') {
			console.log('标准JSON响应，正常解析...')

			if (response.data?.success === true || response.data?.success === undefined) {
				// 成功响应，提取内容
				botContent =
					response.data?.content ||
					response.data?.message ||
					response.data?.data ||
					response.data?.text ||
					response.data?.choices?.[0]?.message?.content ||
					response.data?.result
			} else {
				// 失败响应，显示错误信息
				console.warn('API返回失败响应:', response.data)
				botContent = `[错误] ${response.data?.errorMsg || response.data?.error || '未知错误'}`
			}
		}

		// 如果还是没有内容，显示默认消息
		if (!botContent) {
			botContent = '我收到了你的消息，但暂时无法生成回复。'
			console.warn('无法解析响应内容，使用默认消息')
		}

		console.log('最终提取的回复内容:', botContent)

		// 更新现有的botMessage
		botMessage.content = botContent
		botMessage.rawContent = botContent
		botMessage.isLoading = false
		botMessage.responseTime = Date.now() - botMessage.startTime
		delete botMessage.startTime

		// 重置AI状态为在线
		currentRobot.value.status = '在线'

		console.log('更新的bot消息:', botMessage)
	} catch (error) {
		console.error('普通响应处理失败:', error)
		console.error('错误详情:', error.response?.data)
		throw error
	}
}

// 解析类似流式格式的响应数据
const parseStreamLikeResponse = data => {
	console.log('解析流式格式数据:', data)

	try {
		// 将响应数据按行分割
		const lines = data.split('\n').filter(line => line.trim())
		let fullContent = ''

		for (const line of lines) {
			const trimmedLine = line.trim()

			// 处理 data: 开头的行
			if (trimmedLine.startsWith('data:')) {
				const dataStr = trimmedLine.slice(5).trim()

				if (dataStr && dataStr !== '[DONE]') {
					try {
						const parsed = JSON.parse(dataStr)
						console.log('解析的数据块:', parsed)

						if (parsed.success === true && parsed.content) {
							fullContent += parsed.content
						}
					} catch (e) {
						console.warn('解析数据块失败:', dataStr, e)
					}
				}
			}
		}

		if (fullContent) {
			console.log('合并后的完整内容:', fullContent)
			return fullContent
		}

		// 如果解析失败，尝试提取最后一个完整的数据块
		const lastDataMatch = data.match(/data:\s*(\{[^}]*"content"[^}]*\})/g)
		if (lastDataMatch && lastDataMatch.length > 0) {
			const lastData = lastDataMatch[lastDataMatch.length - 1]
			const jsonStr = lastData.replace('data:', '').trim()
			try {
				const parsed = JSON.parse(jsonStr)
				if (parsed.content) {
					return parsed.content
				}
			} catch (e) {
				console.warn('解析最后数据块失败:', jsonStr, e)
			}
		}

		return '响应解析失败，请重试'
	} catch (error) {
		console.error('流式数据解析错误:', error)
		return '响应解析出错，请重试'
	}
}

// 滚动到聊天底部
const scrollToBottom = () => {
	if (chatContainer.value) {
		chatContainer.value.scrollTop = chatContainer.value.scrollHeight
	}
}

// 处理键盘事件
const handleKeyPress = e => {
	if (e.key === 'Enter' && !e.shiftKey) {
		e.preventDefault()
		sendMessage()
	}
}

// 检测设备类型
const checkDeviceType = () => {
	isMobile.value = window.innerWidth < 768 || 'ontouchstart' in window
}

// 键盘事件处理 - 简化版本
const handleGlobalKeyDown = e => {
	// 仅保留基本的键盘事件处理
}

// 消息格式化函数 - 支持markdown和语法高亮
const formatMessage = content => {
	if (!content) return ''

	let formatted = content
		// 代码块处理 - 使用语法高亮
		.replace(/```(\w*)\n([\s\S]*?)```/g, (match, lang, code) => {
			const trimmedCode = code.trim()
			const langLabel = lang || 'text'
			let highlightedCode = escapeHtml(trimmedCode)

			// 使用highlight.js进行语法高亮
			if (lang && hljs.getLanguage(lang)) {
				try {
					const result = hljs.highlight(trimmedCode, { language: lang })
					highlightedCode = result.value
				} catch (e) {
					console.warn('语法高亮失败:', e)
					// 如果高亮失败，fallback到转义的纯文本
					highlightedCode = escapeHtml(trimmedCode)
				}
			} else if (lang === '' || !lang) {
				// 如果没有指定语言，尝试自动检测
				try {
					const result = hljs.highlightAuto(trimmedCode)
					if (result.relevance > 5) {
						// 只有当检测结果足够可靠时才使用
						highlightedCode = result.value
					}
				} catch (e) {
					console.warn('自动语法检测失败:', e)
				}
			}

			return `
        <div class="code-block" data-language="${langLabel}">
          <div class="code-header-overlay">
            <span class="code-lang-tag">${langLabel || 'text'}</span>
            <button class="copy-code-btn" onclick="copyCodeBlock('${encodeURIComponent(trimmedCode)}', event)">
                            <span class="copy-text">复制</span>
            </button>
          </div>
          <pre><code class="language-${langLabel} hljs">${highlightedCode}</code></pre>
        </div>
      `.trim()
		})
		// 行内代码
		.replace(/`([^`]+)`/g, '<code class="inline-code">$1</code>')
		// 粗体
		.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
		// 斜体
		.replace(/\*(.*?)\*/g, '<em>$1</em>')
		// 链接
		.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" rel="noopener">$1</a>')
		// 换行
		.replace(/\n/g, '<br>')

	return formatted
}

// HTML转义函数
const escapeHtml = text => {
	const div = document.createElement('div')
	div.textContent = text
	return div.innerHTML
}

// 复制代码块功能
window.copyCodeBlock = (encodedCode, event) => {
	const code = decodeURIComponent(encodedCode)
	const button = event?.target?.closest('.copy-code-btn') || event?.currentTarget

	navigator.clipboard
		.writeText(code)
		.then(() => {
			// 添加复制成功的视觉反馈
			if (button) {
				button.classList.add('copied')

				// 临时改变按钮文字和图标
				const originalText = button.innerHTML
				button.innerHTML = `
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
          <path d="M20 6L9 17l-5-5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
        </svg>
        <span class="copy-text">已复制</span>
      `

				// 1.5秒后恢复原状
				setTimeout(() => {
					button.classList.remove('copied')
					button.innerHTML = originalText
				}, 1500)
			}

			message.success('代码已复制到剪贴板', 1.5)
		})
		.catch(() => {
			// 复制失败时的处理
			if (button) {
				button.classList.add('error')
				setTimeout(() => {
					button.classList.remove('error')
				}, 1000)
			}
			message.error('复制失败，请手动复制')
		})
}

// 消息悬停处理
const showCopyButton = messageId => {
	hoveredMessageId.value = messageId
}

const hideCopyButton = () => {
	hoveredMessageId.value = null
}

// 处理复制菜单点击
const handleCopyMenuClick = (event, messageObj) => {
	const key = event.key
	if (key === 'plaintext') {
		copyAsPlainText(messageObj)
	} else if (key === 'markdown') {
		copyAsMarkdown(messageObj)
	}
}

// 复制为纯文本
const copyAsPlainText = messageObj => {
	const textContent = messageObj.content || ''
	// 移除HTML标签，获取纯文本
	const plainText = textContent
		.replace(/<[^>]*>/g, '')
		.replace(/&lt;/g, '<')
		.replace(/&gt;/g, '>')
		.replace(/&amp;/g, '&')

	navigator.clipboard
		.writeText(plainText)
		.then(() => {
			message.success('纯文本已复制到剪贴板')
		})
		.catch(() => {
			// 兜底方案
			fallbackCopy(plainText, '纯文本已复制到剪贴板')
		})
}

// 复制为Markdown格式
const copyAsMarkdown = messageObj => {
	const markdownContent = messageObj.rawContent || messageObj.content || ''

	navigator.clipboard
		.writeText(markdownContent)
		.then(() => {
			message.success('Markdown 格式已复制到剪贴板')
		})
		.catch(() => {
			// 兜底方案
			fallbackCopy(markdownContent, 'Markdown 格式已复制到剪贴板')
		})
}

// 兜底复制方案
const fallbackCopy = (text, successMessage) => {
	const textarea = document.createElement('textarea')
	textarea.value = text
	textarea.style.position = 'fixed'
	textarea.style.opacity = '0'
	document.body.appendChild(textarea)
	textarea.select()
	try {
		document.execCommand('copy')
		message.success(successMessage)
	} catch (e) {
		message.error('复制失败，请手动复制')
	}
	document.body.removeChild(textarea)
}

// ==================== 电话模式功能 ====================

// 开始通话
const startCall = async () => {
	try {
		// 检查roleId是否存在
		if (!roleId.value) {
			message.warning('当前没有选择AI角色，无法进行语音通话')
			return
		}

		isCallMode.value = true
		callState.value = 'calling'
		callDuration.value = 0

		console.log('📞 开始语音通话，使用roleId:', roleId.value)

		// 启动计时器
		callTimer.value = setInterval(() => {
			callDuration.value++
		}, 1000)

		// 开始第一轮对话
		await startVoiceListening()
	} catch (error) {
		console.error('启动通话失败:', error)
		message.error('通话启动失败，请稍后重试')
		endCall()
	}
}

// 结束通话
const endCall = () => {
	isCallMode.value = false
	callState.value = 'ended'

	// 清理音频资源
	cleanupAudio()

	// 清除计时器
	if (callTimer.value) {
		clearInterval(callTimer.value)
		callTimer.value = null
	}

	// 重置状态
	setTimeout(() => {
		callState.value = 'idle'
		callDuration.value = 0
	}, 1000)

	message.success(`通话结束，通话时长 ${formatCallDuration(callDuration.value)}`)
}

// 开始语音监听（调用A接口）
const startVoiceListening = async () => {
	try {
		callState.value = 'listening'

		// 初始化音频监听用于停顿检测
		await initAudioListening()

		// 调用chatAudio接口开始服务端录音
		console.log('🎙️ 调用开始录音接口, roleId:', roleId.value)

		console.log('📡 请求语音录音接口, roleId:', roleId.value)

		const response = await request({
			method: 'POST',
			url: API_CONFIG.ENDPOINTS.VOICE.START_AUDIO,
			params: { roleId: roleId.value },
			timeout: 10000 // 10秒超时
		})

		console.log('🔍 开始录音API响应:', response.data)

		if (response.data.success || response.data.code === 200) {
			console.log('✅ 服务端录音已开始')
		} else {
			console.error('🔴 API返回错误:', response.data)
			throw new Error(response.data.message || response.data.msg || '开始录音失败')
		}

		console.log('开始语音监听...')
	} catch (error) {
		console.error('❌ 开始语音监听失败 - 完整错误信息:', {
			message: error.message,
			response: error.response?.data,
			status: error.response?.status,
			statusText: error.response?.statusText,
			config: {
				url: error.config?.url,
				method: error.config?.method,
				headers: error.config?.headers
			}
		})

		let errorMessage = '语音监听启动失败'
		if (error.response?.data?.message || error.response?.data?.msg) {
			errorMessage += ': ' + (error.response.data.message || error.response.data.msg)
		} else if (error.message) {
			errorMessage += ': ' + error.message
		}

		message.error(errorMessage)
		endCall()
	}
}

// 初始化音频监听
const initAudioListening = async () => {
	try {
		// 获取麦克风权限
		audioStream.value = await navigator.mediaDevices.getUserMedia({
			audio: {
				echoCancellation: true,
				noiseSuppression: true,
				autoGainControl: true,
			},
		})

		// 创建音频上下文
		audioContext.value = new (window.AudioContext || window.webkitAudioContext)()
		const source = audioContext.value.createMediaStreamSource(audioStream.value)

		// 创建分析器
		analyser.value = audioContext.value.createAnalyser()
		analyser.value.fftSize = 256
		source.connect(analyser.value)

		// 开始音量检测
		startVolumeDetection()
	} catch (error) {
		console.error('初始化音频监听失败:', error)
		message.error('无法访问麦克风，请检查权限设置')
		throw error
	}
}

// 开始音量检测
const startVolumeDetection = () => {
	const bufferLength = analyser.value.frequencyBinCount
	const dataArray = new Uint8Array(bufferLength)
	const frequencyData = new Uint8Array(bufferLength)

	const checkVolume = () => {
		if (callState.value !== 'listening') return

		// 获取频谱数据和音量数据
		analyser.value.getByteFrequencyData(dataArray)
		analyser.value.getByteTimeDomainData(frequencyData)

		// 计算当前音量 (RMS)
		let sum = 0
		for (let i = 0; i < bufferLength; i++) {
			const normalized = (frequencyData[i] - 128) / 128
			sum += normalized * normalized
		}
		const rms = Math.sqrt(sum / bufferLength)
		currentVolume.value = Math.min(rms * 10, 1) // 放大并限制到0-1

		// 语音频谱分析 (300Hz-3000Hz 是主要语音频段)
		const voiceEnergyRatio = calculateVoiceEnergyRatio(dataArray)

		// 维护音量历史记录 (最近10个样本)
		volumeHistory.value.push(currentVolume.value)
		if (volumeHistory.value.length > 10) {
			volumeHistory.value.shift()
		}

		// 校准模式：收集环境音样本
		if (isCalibrating.value) {
			calibrationSamples.value.push(currentVolume.value)
			if (calibrationSamples.value.length >= 50) {
				// 收集50个样本约1.5秒
				finishCalibration()
			}
		} else {
			// 语音活动检测
			const wasSpeaking = isSpeaking.value
			isSpeaking.value = detectVoiceActivity(currentVolume.value, voiceEnergyRatio)

			// 检测说话状态变化
			if (wasSpeaking && !isSpeaking.value) {
				// 从说话变为静音，开始计时
				startSilenceTimer()
			} else if (!wasSpeaking && isSpeaking.value) {
				// 从静音变为说话，取消计时
				clearSilenceTimer()
			}
		}

		// 继续检测
		requestAnimationFrame(checkVolume)
	}

	checkVolume()
}

// 计算语音能量比例
const calculateVoiceEnergyRatio = frequencyData => {
	const sampleRate = audioContext.value.sampleRate
	const binSize = sampleRate / analyser.value.fftSize

	// 语音频段 300Hz-3000Hz
	const voiceStartBin = Math.floor(300 / binSize)
	const voiceEndBin = Math.floor(3000 / binSize)

	let voiceEnergy = 0
	let totalEnergy = 0

	for (let i = 0; i < frequencyData.length; i++) {
		const energy = frequencyData[i] * frequencyData[i]
		totalEnergy += energy

		if (i >= voiceStartBin && i <= voiceEndBin) {
			voiceEnergy += energy
		}
	}

	return totalEnergy > 0 ? voiceEnergy / totalEnergy : 0
}

// 语音活动检测
const detectVoiceActivity = (volume, voiceEnergyRatio) => {
	// 基于敏感度计算动态阈值
	const dynamicThreshold = baselineVolume.value + volumeThreshold.value * sensitivity.value

	// 条件1：音量超过动态阈值
	const volumeCondition = volume > dynamicThreshold

	// 条件2：语音频段能量占比足够高
	const voiceCondition = voiceEnergyRatio > 0.3

	// 条件3：音量变化趋势 (最近几个样本的平均值)
	const recentAvg = volumeHistory.value.length > 0 ? volumeHistory.value.reduce((a, b) => a + b, 0) / volumeHistory.value.length : 0
	const trendCondition = volume > recentAvg * 1.2

	// 综合判断：音量条件 + (语音条件 或 趋势条件)
	return volumeCondition && (voiceCondition || trendCondition)
}

// 开始环境音校准
const startCalibration = () => {
	isCalibrating.value = true
	calibrationSamples.value = []
	volumeHistory.value = []
	console.log('开始环境基线校准，请保持安静...')
}

// 完成校准
const finishCalibration = () => {
	if (calibrationSamples.value.length === 0) return

	// 计算环境基线音量 (取中位数，排除异常值)
	const sortedSamples = [...calibrationSamples.value].sort((a, b) => a - b)
	const medianIndex = Math.floor(sortedSamples.length / 2)
	baselineVolume.value = sortedSamples[medianIndex]

	// 根据环境调整基础阈值
	volumeThreshold.value = Math.max(baselineVolume.value * 2, 0.02)

	console.log(`环境校准完成: 基线=${baselineVolume.value.toFixed(3)}, 阈值=${volumeThreshold.value.toFixed(3)}`)
	message.success(`环境校准完成！基线音量: ${(baselineVolume.value * 100).toFixed(1)}%`)

	isCalibrating.value = false
	calibrationSamples.value = []
}

// 调整敏感度
const setSensitivity = level => {
	sensitivity.value = level
	console.log(`敏感度设为: ${level}级`)
}

// 开始静音计时
const startSilenceTimer = () => {
	clearSilenceTimer()

	silenceTimer.value = setTimeout(() => {
		if (callState.value === 'listening' && !isSpeaking.value) {
			console.log('检测到停顿，自动发送语音')
			sendVoiceInput()
		}
	}, silenceThreshold.value)
}

// 清除静音计时
const clearSilenceTimer = () => {
	if (silenceTimer.value) {
		clearTimeout(silenceTimer.value)
		silenceTimer.value = null
	}
}

// 清理音频资源
const cleanupAudio = () => {
	clearSilenceTimer()

	if (audioStream.value) {
		audioStream.value.getTracks().forEach(track => track.stop())
		audioStream.value = null
	}

	if (audioContext.value) {
		audioContext.value.close()
		audioContext.value = null
	}

	analyser.value = null
	isSpeaking.value = false
}

// 停止语音并处理（调用B接口）
const stopVoiceAndProcess = async () => {
	try {
		callState.value = 'thinking'

		// 暂停音频监听
		cleanupAudio()

		console.log('🔄 调用停止录音接口，获取AI音频响应...')

		console.log('📡 请求停止录音接口')

		// 调用stopAudioASR接口停止录音并获取AI音频响应
		const response = await request({
			method: 'POST',
			url: API_CONFIG.ENDPOINTS.VOICE.STOP_AUDIO,
			responseType: 'blob', // 期望返回音频文件
			timeout: 30000 // 30秒超时，因为AI处理可能需要时间
		})

		console.log('✅ 收到AI音频响应, 类型:', response.headers['content-type'], '大小:', response.data.size, 'bytes')

		// 检查返回的是否为音频文件
		if (response.data.size === 0) {
			throw new Error('收到空的音频文件')
		}

		// 播放AI回复
		await playAIResponse(response.data)
	} catch (error) {
		console.error('❌ 语音处理失败 - 完整错误信息:', {
			message: error.message,
			response: error.response?.data,
			status: error.response?.status,
			statusText: error.response?.statusText,
			config: {
				url: error.config?.url,
				method: error.config?.method,
				headers: error.config?.headers
			}
		})

		let errorMessage = '语音处理失败，请重试'
		if (error.response?.data?.message || error.response?.data?.msg) {
			errorMessage += ': ' + (error.response.data.message || error.response.data.msg)
		} else if (error.message) {
			errorMessage += ': ' + error.message
		}

		message.error(errorMessage)
		// 回到监听状态
		await startVoiceListening()
	}
}

// 播放AI音频回复
const playAIResponse = async (audioBlob) => {
	try {
		callState.value = 'speaking'

		if (!audioBlob) {
			throw new Error('未收到音频数据')
		}

		console.log('🔊 开始播放AI音频回复...')

		// 创建音频对象并播放
		const audioUrl = URL.createObjectURL(audioBlob)
		const audio = new Audio(audioUrl)

		// 设置音频播放完成的回调
		return new Promise((resolve, reject) => {
			audio.onended = () => {
				console.log('✅ AI音频播放完成')
				URL.revokeObjectURL(audioUrl) // 清理资源
				resolve()
			}

			audio.onerror = (error) => {
				console.error('❌ 音频播放出错:', error)
				URL.revokeObjectURL(audioUrl) // 清理资源
				reject(new Error('音频播放失败'))
			}

			// 播放音频
			audio.play().catch(error => {
				console.error('❌ 无法播放音频:', error)
				URL.revokeObjectURL(audioUrl)
				reject(error)
			})
		}).then(() => {
			// 播放完成后回到监听状态
			if (callState.value === 'speaking') {
				return startVoiceListening()
			}
		}).catch(error => {
			console.error('❌ 播放AI音频失败:', error)
			message.error('音频播放失败: ' + error.message)
			// 即使播放失败也要回到监听状态
			if (callState.value === 'speaking') {
				return startVoiceListening()
			}
		})
	} catch (error) {
		console.error('❌ 播放AI音频失败:', error)
		message.error('音频播放失败: ' + (error.message || error.toString()))
		// 回到监听状态
		await startVoiceListening()
	}
}

// 格式化通话时长
const formatCallDuration = seconds => {
	const mins = Math.floor(seconds / 60)
	const secs = seconds % 60
	return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
}

// 用户手动发送语音（在监听状态下）
const sendVoiceInput = async () => {
	if (callState.value === 'listening') {
		await stopVoiceAndProcess()
	}
}

// 测试API连接
const testAPIConnection = async () => {
	try {
		if (!roleId.value) {
			message.warning('请先选择一个AI角色')
			return
		}

		console.log('🧪 测试API连接...')
		message.loading('测试API连接...', 0)

		console.log('🔗 测试语音API接口, roleId:', roleId.value)

		const response = await request({
			method: 'POST',
			url: API_CONFIG.ENDPOINTS.VOICE.START_AUDIO,
			params: { roleId: roleId.value },
			timeout: 10000
		})

		console.log('✅ API测试成功:', response.data)
		message.destroy()
		message.success('API连接测试成功！')

		// 如果测试成功，立即调用停止接口避免服务端一直录音
		try {
			await request({
				method: 'POST',
				url: API_CONFIG.ENDPOINTS.VOICE.STOP_AUDIO
			})
			console.log('🛑 已调用停止录音接口')
		} catch (stopError) {
			console.warn('⚠️ 停止录音接口调用失败:', stopError)
		}

	} catch (error) {
		console.error('❌ API测试失败:', error)
		message.destroy()

		let errorMsg = 'API连接测试失败'
		if (error.response?.data?.message || error.response?.data?.msg) {
			errorMsg += ': ' + (error.response.data.message || error.response.data.msg)
		} else if (error.message) {
			errorMsg += ': ' + error.message
		}

		message.error(errorMsg)
	}
}

// 重新生成回复
const regenerateResponse = async messageObj => {
	try {
		const messageIndex = messages.value.findIndex(msg => msg.id === messageObj.id)
		if (messageIndex === -1) return

		// 找到对应的用户消息
		const userMessage = messages.value[messageIndex - 1]
		if (!userMessage || userMessage.type !== 'user') {
			message.error('操作失败，请重试')
			return
		}

		// 移除原来的bot消息
		messages.value.splice(messageIndex, 1)

		// 创建新的AI消息占位符，显示加载状态
		const startTime = Date.now()
		const botMessage = {
			id: Date.now() + 1,
			type: 'bot',
			content: '',
			rawContent: '',
			timestamp: new Date().toLocaleString('zh-CN'),
			isLoading: true,
			startTime: startTime,
		}
		messages.value.push(botMessage)

		// 滚动到底部显示加载状态
		await nextTick()
		if (chatSettings.value.autoScroll) {
			scrollToBottom()
		}

		// 设置连接状态
		isConnecting.value = true
		isTyping.value = true

		// 根据输出模式更新AI状态
		if (chatSettings.value.streamOutput) {
			currentRobot.value.status = 'AI输入中'
		} else {
			currentRobot.value.status = 'AI思考中'
		}

		// 构建消息历史（不包含当前占位消息）
		const messageList = messages.value
			.filter(msg => !msg.isLoading)
			.map(msg => ({
				role: msg.type === 'user' ? 'user' : 'assistant',
				content: msg.content,
			}))

		const requestData = {
			messageList: messageList,
			isStream: chatSettings.value.streamOutput,
			// 如果有roleId，则添加到请求中
			...(roleId.value && { roleId: roleId.value })
		}

		console.log('重新生成API请求:', requestData)
		console.log('重新生成时roleId:', roleId.value, 'ID类型:', typeof roleId.value)

		if (chatSettings.value.streamOutput) {
			await handleStreamResponse(requestData, botMessage)
		} else {
			await handleNormalResponse(requestData, botMessage)
		}
	} catch (error) {
		console.error('重新生成失败:', error)
		message.error('重新生成失败，请稍后重试')
	} finally {
		isConnecting.value = false
		isTyping.value = false
		// 确保AI状态重置为在线（除非已经在处理成功响应中重置）
		if (currentRobot.value.status !== '在线') {
			currentRobot.value.status = '在线'
		}
	}
}

// 格式化响应时间显示
const formatResponseTime = ms => {
	if (ms < 1000) {
		return `${ms}ms`
	} else if (ms < 60000) {
		return `${(ms / 1000).toFixed(1)}s`
	} else {
		return `${Math.floor(ms / 60000)}m ${Math.floor((ms % 60000) / 1000)}s`
	}
}

// 设置功能
const toggleStreamMode = () => {
	chatSettings.value.streamOutput = !chatSettings.value.streamOutput
	const mode = chatSettings.value.streamOutput ? '实时打字' : '完整回复'
	message.success(`已切换到${mode}模式`)
}

const toggleAutoScroll = () => {
	chatSettings.value.autoScroll = !chatSettings.value.autoScroll
	const status = chatSettings.value.autoScroll ? '开启' : '关闭'
	message.info(`自动滚动已${status}`)
}

const toggleTimestamp = () => {
	chatSettings.value.showTimestamp = !chatSettings.value.showTimestamp
	const status = chatSettings.value.showTimestamp ? '显示' : '隐藏'
	message.info(`时间戳${status}`)
}

const clearChat = () => {
	messages.value = [...mockMessages] // 重置为初始消息
	message.success('对话记录已清空')
	nextTick(() => scrollToBottom())
}

const exportChat = () => {
	const chatData = {
		robot: currentRobot.value,
		messages: messages.value,
		settings: chatSettings.value,
		exportTime: new Date().toISOString(),
	}

	const dataStr = JSON.stringify(chatData, null, 2)
	const dataBlob = new Blob([dataStr], { type: 'application/json' })

	const link = document.createElement('a')
	link.href = URL.createObjectURL(dataBlob)
	link.download = `chat-${currentRobot.value.name}-${new Date().toISOString().slice(0, 10)}.json`
	link.click()

	message.success('对话记录已导出')
}

// 组件挂载后加载初始消息和事件监听
onMounted(() => {
	// 获取路由参数中的roleId（保持字符串格式避免大整数精度丢失）
	if (route.query.roleId) {
		roleId.value = route.query.roleId.toString()
		console.log('获取到roleId:', roleId.value, 'ID类型:', typeof roleId.value)
	}

	messages.value = [...mockMessages]
	nextTick(() => scrollToBottom())

	// 检测设备类型
	checkDeviceType()
	window.addEventListener('resize', checkDeviceType)

	// 桌面端键盘事件监听
	if (!isMobile.value) {
		document.addEventListener('keydown', handleGlobalKeyDown)
	}
})

// 组件卸载时清理
onUnmounted(() => {
	// 清理定时器和录音
	if (recordingTimer) {
		clearInterval(recordingTimer)
	}

	if (recognition) {
		recognition.stop()
	}

	if (mediaRecorder && mediaRecorder.state !== 'inactive') {
		mediaRecorder.stop()
	}

	// 移除事件监听器
	window.removeEventListener('resize', checkDeviceType)
	document.removeEventListener('keydown', handleGlobalKeyDown)
})
</script>

<template>
	<div class="page-container chat-page">
		<!-- 游客体验公告 -->
		<div
			v-if="!authStore.isAuthenticated && showGuestNotice"
			class="guest-notice-popup"
		>
			<div class="notice-header">
				<div class="notice-icon">
					<svg
						width="16"
						height="16"
						viewBox="0 0 24 24"
						fill="none"
						stroke="currentColor"
						stroke-width="2"
						stroke-linecap="round"
						stroke-linejoin="round"
					>
						<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path>
						<path d="M13.73 21a2 2 0 0 1-3.46 0"></path>
					</svg>
				</div>
				<span class="notice-title">游客体验提示</span>
				<button
					class="close-btn"
					@click="closeGuestNotice"
				>
					×
				</button>
			</div>
			<div class="notice-content">
				<!-- 桌面端显示完整信息 -->
				<template v-if="!isMobile">
					<p>您当前是游客身份，仅可体验有限功能</p>
					<p v-if="remainingMessages !== null">
						剩余
						<strong>{{ remainingMessages }}</strong>
						次对话机会
					</p>
				</template>
				<!-- 移动端显示简洁信息 -->
				<template v-else>
					<p v-if="remainingMessages !== null">
						游客体验：剩余
						<strong>{{ remainingMessages }}</strong>
						次对话
					</p>
					<p v-else>游客体验模式，功能受限</p>
				</template>
				<div class="notice-actions">
					<button
						class="login-btn"
						@click="handleGoToLogin"
					>
						立即登录
					</button>
					<button
						class="register-btn"
						@click="handleGoToRegister"
					>
						免费注册
					</button>
				</div>
			</div>
		</div>

		<!-- 聊天头部 -->
		<div class="chat-header">
			<div class="robot-info">
				<Avatar
					:src="robotAvatar"
					:size="48"
				/>
				<div class="robot-details">
					<h3 class="robot-name">{{ robotName }}</h3>
					<p class="robot-status">
						<span class="status-indicator online"></span>
						{{ currentRobot.status }}
					</p>
				</div>
			</div>
			<div class="chat-actions">
				<Dropdown
					:trigger="['click']"
					placement="bottomRight"
				>
					<Button
						type="text"
						size="small"
						class="settings-btn"
					>
						<template #icon>
							<SettingOutlined :spin="isConnecting" />
						</template>
						<span v-if="!isMobile">设置</span>
					</Button>
					<template #overlay>
						<Menu class="settings-menu">
							<MenuItem
								key="stream-mode"
								class="setting-item"
							>
								<div class="setting-content">
									<div class="setting-info">
										<div class="setting-text">
											<div class="setting-title">
												{{ chatSettings.streamOutput ? '实时打字' : '完整回复' }}
											</div>
											<div class="setting-desc">
												{{ chatSettings.streamOutput ? '逐字显示AI回复内容' : '等待完整回复后显示' }}
											</div>
										</div>
									</div>
									<Switch
										:checked="chatSettings.streamOutput"
										@change="toggleStreamMode"
										size="small"
									/>
								</div>
							</MenuItem>
							<MenuItem
								key="auto-scroll"
								class="setting-item"
							>
								<div class="setting-content">
									<div class="setting-info">
										<div class="setting-text">
											<div class="setting-title">自动滚动</div>
											<div class="setting-desc">新消息时自动滚动到底部</div>
										</div>
									</div>
									<Switch
										:checked="chatSettings.autoScroll"
										@change="toggleAutoScroll"
										size="small"
									/>
								</div>
							</MenuItem>
							<MenuItem
								key="timestamp"
								class="setting-item"
							>
								<div class="setting-content">
									<div class="setting-info">
										<div class="setting-text">
											<div class="setting-title">显示时间</div>
											<div class="setting-desc">在消息下方显示时间戳</div>
										</div>
									</div>
									<Switch
										:checked="chatSettings.showTimestamp"
										@change="toggleTimestamp"
										size="small"
									/>
								</div>
							</MenuItem>
							<Menu.Divider />
							<MenuItem
								key="clear"
								@click="clearChat"
								class="action-item"
							>
								<span class="action-text">清空对话</span>
							</MenuItem>
							<MenuItem
								key="export"
								@click="exportChat"
								class="action-item"
							>
								<span class="action-text">导出记录</span>
							</MenuItem>
						</Menu>
					</template>
				</Dropdown>
			</div>
		</div>

		<!-- 聊天内容区域 -->
		<div
			class="chat-container"
			ref="chatContainer"
		>
			<div class="chat-content">
				<!-- 欢迎消息 -->
				<div class="welcome-message">
					<Avatar
						:src="robotAvatar"
						:size="64"
					/>
					<h3>与 {{ robotName }} 对话</h3>
					<p>{{ currentRobot.description }}</p>
				</div>

				<!-- 消息列表 -->
				<div class="messages-list">
					<div
						v-for="message in messages"
						:key="message.id"
						class="message-item"
						:class="message.type"
					>
						<Avatar
							v-if="message.type === 'bot'"
							:src="robotAvatar"
							:size="36"
							class="message-avatar"
						/>
						<div
							class="message-content"
							@mouseenter="showCopyButton(message.id)"
							@mouseleave="hideCopyButton(message.id)"
						>
							<div
								class="message-bubble"
								:class="[message.type, { error: message.isError, streaming: message.isStreaming }]"
							>
								<!-- 消息内容 -->
								<div
									class="message-text"
									v-if="message.content || message.isStreaming || message.isLoading"
								>
									<!-- 消息内容（始终显示，如果有内容、不在加载中，或者正在流式输出） -->
									<div v-if="message.content || !message.isLoading || message.isStreaming">
										<!-- 使用v-html渲染markdown -->
										<span
											v-if="message.type === 'bot'"
											v-html="formatMessage(message.content)"
										></span>
										<span v-else>{{ message.content }}</span>
									</div>

									<!-- 初始加载状态显示（等待AI响应时） -->
									<div
										v-if="message.isLoading && !message.content && !message.isStreaming"
										class="initial-loading"
									>
										<span class="loading-dots">
											<span class="dot"></span>
											<span class="dot"></span>
											<span class="dot"></span>
										</span>
									</div>

									<!-- 流式输入时的加载指示器（在文字后面） -->
									<span
										v-if="message.isStreaming"
										class="inline-loading"
									>
										<span class="loading-dots">
											<span class="dot"></span>
											<span class="dot"></span>
											<span class="dot"></span>
										</span>
									</span>
								</div>

								<!-- 消息功能按钮组 -->
								<div
									v-show="hoveredMessageId === message.id"
									class="message-actions"
								>
									<!-- AI消息功能按钮组 -->
									<template v-if="message.type === 'bot'">
										<div
											class="action-button"
											@click="regenerateResponse(message)"
											title="重新生成"
										>
											<svg
												width="14"
												height="14"
												viewBox="0 0 24 24"
												fill="none"
											>
												<path
													d="M23 4v6h-6"
													stroke="currentColor"
													stroke-width="2"
												/>
												<path
													d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"
													stroke="currentColor"
													stroke-width="2"
												/>
											</svg>
										</div>
										<div
											class="action-button copy-text-btn"
											@click="copyAsPlainText(message)"
											title="复制文本"
										>
											<svg
												width="14"
												height="14"
												viewBox="0 0 24 24"
												fill="none"
											>
												<rect
													x="9"
													y="9"
													width="13"
													height="13"
													rx="2"
													ry="2"
													stroke="currentColor"
													stroke-width="2"
												/>
												<path
													d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"
													stroke="currentColor"
													stroke-width="2"
												/>
											</svg>
										</div>
										<div
											class="action-button copy-markdown-btn"
											@click="copyAsMarkdown(message)"
											title="复制Markdown"
										>
											<svg
												width="14"
												height="14"
												viewBox="0 0 24 24"
												fill="none"
											>
												<path
													d="M14 3v4a1 1 0 0 0 1 1h4"
													stroke="currentColor"
													stroke-width="2"
												/>
												<path
													d="M12 21H6a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h6l6 6v4"
													stroke="currentColor"
													stroke-width="2"
												/>
												<path
													d="M16 19l-4-4 4-4"
													stroke="currentColor"
													stroke-width="2"
												/>
											</svg>
										</div>
										<!-- 响应时间显示 -->
										<div
											v-if="message.responseTime"
											class="response-time"
											:title="`响应时间: ${message.responseTime}ms`"
										>
											{{ formatResponseTime(message.responseTime) }}
										</div>
									</template>

									<!-- 用户消息功能按钮组 - 只显示复制文本按钮 -->
									<template v-else-if="message.type === 'user'">
										<div
											class="action-button copy-text-btn"
											@click="copyAsPlainText(message)"
											title="复制文本"
										>
											<svg
												width="14"
												height="14"
												viewBox="0 0 24 24"
												fill="none"
											>
												<rect
													x="9"
													y="9"
													width="13"
													height="13"
													rx="2"
													ry="2"
													stroke="currentColor"
													stroke-width="2"
												/>
												<path
													d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"
													stroke="currentColor"
													stroke-width="2"
												/>
											</svg>
										</div>
									</template>
								</div>
							</div>
							<div
								v-if="chatSettings.showTimestamp"
								class="message-time"
							>
								{{ message.timestamp }}
							</div>
						</div>
					</div>
				</div>

				<!-- 移除独立的正在输入指示器，改为集成在消息内部 -->
			</div>
		</div>

		<!-- 输入区域 -->
		<div class="chat-input">
			<!-- 桌面端输入框 -->
			<div
				v-if="!isMobile"
				class="input-container"
			>
				<!-- 电话模式按钮 -->
				<Button
					type="text"
					class="call-btn"
					@click="startCall"
					:disabled="isCallMode"
					title="语音通话"
				>
					<template #icon>
						<svg
							width="20"
							height="20"
							viewBox="0 0 24 24"
							fill="none"
							stroke="currentColor"
							stroke-width="2"
						>
							<path
								d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"
							/>
						</svg>
					</template>
				</Button>

				<!-- API测试按钮 -->
				<Button
					type="text"
					class="test-api-btn"
					@click="testAPIConnection"
					:disabled="isCallMode"
					title="测试语音API连接"
				>
					<template #icon>
						<svg
							width="16"
							height="16"
							viewBox="0 0 24 24"
							fill="none"
							stroke="currentColor"
							stroke-width="2"
						>
							<polyline points="20,6 9,17 4,12"/>
						</svg>
					</template>
				</Button>

				<!-- 文字输入模式 -->
				<div class="input-wrapper">
					<Input.TextArea
						v-model:value="inputText"
						placeholder="输入你的消息..."
						:rows="1"
						:auto-size="{ minRows: 1, maxRows: 4 }"
						@keypress="handleKeyPress"
						class="message-input"
					/>
				</div>

				<Button
					type="primary"
					@click="sendMessage"
					:disabled="!inputText.trim() || isConnecting"
					:loading="isConnecting"
					class="send-btn"
				>
					<template #icon>
						<SendOutlined v-if="!isConnecting" />
					</template>
				</Button>
			</div>

			<!-- 移动端输入框 -->
			<div
				v-else
				class="mobile-input-container"
			>
				<!-- 电话模式按钮 -->
				<Button
					type="text"
					class="call-btn"
					@click="startCall"
					:disabled="isCallMode"
					title="语音通话"
				>
					<template #icon>
						<svg
							width="20"
							height="20"
							viewBox="0 0 24 24"
							fill="none"
							stroke="currentColor"
							stroke-width="2"
						>
							<path
								d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"
							/>
						</svg>
					</template>
				</Button>

				<!-- 文字输入模式 -->
				<template>
					<Input.TextArea
						v-model:value="inputText"
						placeholder="输入你的消息..."
						:rows="1"
						:auto-size="{ minRows: 1, maxRows: 3 }"
						@keypress="handleKeyPress"
						class="message-input"
					/>
				</template>

				<Button
					type="primary"
					@click="sendMessage"
					:disabled="!inputText.trim() || isConnecting"
					:loading="isConnecting"
					class="send-btn"
				>
					<template #icon>
						<SendOutlined v-if="!isConnecting" />
					</template>
				</Button>
			</div>
		</div>

		<!-- 全屏电话界面 -->
		<div
			v-if="isCallMode"
			class="call-interface"
			:class="{ mobile: isMobile }"
		>
			<!-- 电话界面内容 -->
			<div class="call-content">
				<!-- 头部信息 -->
				<div class="call-header">
					<div class="call-title">🤖 AI助手</div>
					<div class="call-duration">{{ formatCallDuration(callDuration) }}</div>
					<div class="call-status">
						<span v-if="callState === 'calling'">正在连接...</span>
						<span
							v-else-if="callState === 'listening'"
							class="listening"
						>
							<span v-if="isCalibrating">📊 环境音校准中... ({{ calibrationSamples.length }}/30)</span>
							<span v-else-if="isSpeaking">🎤 正在说话...</span>
							<span v-else>⏸️ 等待说话 ({{ Math.ceil(silenceThreshold / 1000) }}秒后自动发送)</span>
						</span>
						<span
							v-else-if="callState === 'thinking'"
							class="thinking"
						>
							🤔 AI思考中...
						</span>
						<span
							v-else-if="callState === 'speaking'"
							class="speaking"
						>
							🗣️ AI正在回答
						</span>
					</div>

					<!-- 音频监控信息 -->
					<div
						v-if="callState === 'listening'"
						class="audio-monitor"
					>
						<div class="volume-display">
							<span class="label">音量:</span>
							<span
								class="value"
								:class="{ speaking: isSpeaking }"
							>
								{{ (currentVolume * 100).toFixed(1) }}%
							</span>
						</div>
						<div class="threshold-display">
							<span class="label">敏感度:</span>
							<span class="value">{{ sensitivity }}级</span>
						</div>
						<div class="baseline-display">
							<span class="label">环境:</span>
							<span class="value">{{ (baselineVolume * 100).toFixed(1) }}%</span>
						</div>
					</div>

					<!-- 设置按钮 -->
					<button
						v-if="callState === 'listening'"
						class="audio-settings-btn"
						@click="showAudioSettings = true"
						title="音频设置"
					>
						<svg
							width="16"
							height="16"
							viewBox="0 0 24 24"
							fill="none"
							stroke="currentColor"
							stroke-width="2"
						>
							<circle
								cx="12"
								cy="12"
								r="3"
							/>
							<path d="M12 1v6m0 10v6m11-5h-6m-10 0H1" />
						</svg>
					</button>
				</div>

				<!-- 中央可视化区域 -->
				<div class="call-visual">
					<!-- PC端水波纹球体 -->
					<div
						v-if="!isMobile"
						class="wave-sphere"
					>
						<div
							class="sphere"
							:class="{
								listening: callState === 'listening',
								thinking: callState === 'thinking',
								speaking: callState === 'speaking',
								'user-speaking': callState === 'listening' && isSpeaking,
							}"
						>
							<div class="wave wave1"></div>
							<div class="wave wave2"></div>
							<div class="wave wave3"></div>
							<div class="inner-circle">
								<svg
									width="60"
									height="60"
									viewBox="0 0 24 24"
									fill="none"
									stroke="currentColor"
									stroke-width="1.5"
								>
									<path
										v-if="callState === 'listening'"
										d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"
									/>
									<path
										v-if="callState === 'listening'"
										d="M19 10v2a7 7 0 0 1-14 0v-2"
									/>
									<path
										v-if="callState === 'thinking'"
										d="M12 3c7.2 0 9 1.8 9 9s-1.8 9-9 9-9-1.8-9-9 1.8-9 9-9"
									/>
									<path
										v-if="callState === 'speaking'"
										d="M3 11l7-4v3h8v2H10v3l-7-4z"
									/>
								</svg>
							</div>
						</div>
					</div>

					<!-- 移动端简化界面 -->
					<div
						v-else
						class="mobile-visual"
					>
						<div
							class="mobile-icon"
							:class="{
								listening: callState === 'listening',
								thinking: callState === 'thinking',
								speaking: callState === 'speaking',
								'user-speaking': callState === 'listening' && isSpeaking,
							}"
						>
							<svg
								width="80"
								height="80"
								viewBox="0 0 24 24"
								fill="none"
								stroke="currentColor"
								stroke-width="1.5"
							>
								<path
									v-if="callState === 'listening'"
									d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"
								/>
								<path
									v-if="callState === 'listening'"
									d="M19 10v2a7 7 0 0 1-14 0v-2"
								/>
								<circle
									v-if="callState === 'thinking'"
									cx="12"
									cy="12"
									r="10"
								/>
								<path
									v-if="callState === 'speaking'"
									d="M3 11l7-4v3h8v2H10v3l-7-4z"
								/>
							</svg>
						</div>
						<div class="mobile-ripple">
							<div class="ripple ripple1"></div>
							<div class="ripple ripple2"></div>
							<div class="ripple ripple3"></div>
						</div>
					</div>
				</div>

				<!-- 控制按钮 -->
				<div class="call-controls">
					<Button
						v-if="callState === 'listening'"
						type="primary"
						class="send-voice-btn"
						@click="sendVoiceInput"
						size="large"
					>
						<template #icon>
							<svg
								width="20"
								height="20"
								viewBox="0 0 24 24"
								fill="none"
								stroke="currentColor"
								stroke-width="2"
							>
								<polygon points="13,2 3,14 12,14 11,22 21,10 12,10 13,2" />
							</svg>
						</template>
						发送
					</Button>

					<Button
						type="primary"
						danger
						class="end-call-btn"
						@click="endCall"
						size="large"
					>
						<template #icon>
							<svg
								width="20"
								height="20"
								viewBox="0 0 24 24"
								fill="none"
								stroke="currentColor"
								stroke-width="2"
							>
								<path
									d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"
								/>
							</svg>
						</template>
						挂断
					</Button>
				</div>
			</div>

			<!-- 音频设置面板 -->
			<div
				v-if="showAudioSettings"
				class="audio-settings-panel"
			>
				<div class="settings-content">
					<div class="settings-header">
						<h3>🎙️ 音频设置</h3>
						<button
							class="close-btn"
							@click="showAudioSettings = false"
						>
							<svg
								width="20"
								height="20"
								viewBox="0 0 24 24"
								fill="none"
								stroke="currentColor"
								stroke-width="2"
							>
								<line
									x1="18"
									y1="6"
									x2="6"
									y2="18"
								/>
								<line
									x1="6"
									y1="6"
									x2="18"
									y2="18"
								/>
							</svg>
						</button>
					</div>

					<div class="settings-body">
						<!-- 环境音校准 -->
						<div class="setting-group">
							<div class="setting-title">环境音校准</div>
							<div class="setting-description">校准环境底噪，提高语音检测准确性。请在安静环境下点击校准。</div>
							<div class="calibration-controls">
								<Button
									type="primary"
									@click="startCalibration"
									:disabled="isCalibrating"
									:loading="isCalibrating"
								>
									{{ isCalibrating ? '校准中...' : '开始校准' }}
								</Button>
								<div class="calibration-info">
									<span>环境基线: {{ (baselineVolume * 100).toFixed(1) }}%</span>
									<span>当前音量: {{ (currentVolume * 100).toFixed(1) }}%</span>
								</div>
							</div>
						</div>

						<!-- 敏感度设置 -->
						<div class="setting-group">
							<div class="setting-title">语音检测敏感度</div>
							<div class="setting-description">调节语音检测的敏感度等级。敏感度越高，越容易检测到语音。</div>
							<div class="sensitivity-controls">
								<div class="sensitivity-slider">
									<label>敏感度: {{ sensitivity }}级</label>
									<input
										type="range"
										v-model="sensitivity"
										min="1"
										max="5"
										step="1"
										class="slider"
									/>
									<div class="range-labels">
										<span>1级 (不敏感)</span>
										<span>5级 (非常敏感)</span>
									</div>
								</div>
								<div class="sensitivity-presets">
									<button
										@click="setSensitivity(2)"
										class="preset-btn"
									>
										安静环境 (2级)
									</button>
									<button
										@click="setSensitivity(3)"
										class="preset-btn"
									>
										普通环境 (3级)
									</button>
									<button
										@click="setSensitivity(4)"
										class="preset-btn"
									>
										嘈杂环境 (4级)
									</button>
								</div>
							</div>
						</div>

						<!-- 检测阈值设置 -->
						<div class="setting-group">
							<div class="setting-title">音量阈值调节</div>
							<div class="setting-description">精细调节音量检测阈值。建议先进行环境校准，再调节此项。</div>
							<div class="threshold-controls">
								<div class="threshold-slider">
									<label>阈值: {{ (volumeThreshold * 100).toFixed(1) }}%</label>
									<input
										type="range"
										v-model="volumeThreshold"
										min="0.01"
										max="0.2"
										step="0.01"
										class="slider"
									/>
									<div class="range-labels">
										<span>1% (敏感)</span>
										<span>20% (迟钝)</span>
									</div>
								</div>
								<div class="threshold-info">
									<span>动态阈值: {{ ((baselineVolume + volumeThreshold * sensitivity) * 100).toFixed(1) }}%</span>
								</div>
							</div>
						</div>

						<!-- 停顿时长设置 -->
						<div class="setting-group">
							<div class="setting-title">停顿检测时长</div>
							<div class="setting-description">设置多长时间的停顿后自动发送语音</div>
							<div class="silence-controls">
								<label>停顿时长: {{ (silenceThreshold / 1000).toFixed(1) }}秒</label>
								<input
									type="range"
									v-model="silenceThreshold"
									min="1000"
									max="5000"
									step="500"
									class="slider"
								/>
								<div class="range-labels">
									<span>1秒 (快速)</span>
									<span>5秒 (慢速)</span>
								</div>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>

	<!-- 游客对话限制提示Modal -->
	<Modal
		v-model:open="showLoginModal"
		title="需要登录才能继续对话"
		:footer="null"
		:closable="false"
		:maskClosable="false"
		centered
		class="login-prompt-modal"
	>
		<div class="login-prompt-content">
			<div class="prompt-icon">🔒</div>
			<h3 class="prompt-title">体验次数已用完</h3>
			<p class="prompt-description">
				您已体验了 {{ GUEST_MESSAGE_LIMIT }} 次免费对话。
				<br />
				登录后可享受无限制对话服务！
			</p>
			<div class="prompt-actions">
				<Button
					type="primary"
					size="large"
					@click="handleGoToLogin"
					class="login-btn"
				>
					立即登录
				</Button>
				<Button
					size="large"
					@click="handleGoToRegister"
					class="register-btn"
				>
					免费注册
				</Button>
			</div>
			<div class="prompt-footer">
				<Button
					type="text"
					size="small"
					@click="handleCloseLoginModal"
					class="close-btn"
				>
					稍后再说
				</Button>
			</div>
		</div>
	</Modal>
</template>

<style lang="scss" scoped>
.chat-page {
	display: flex;
	flex-direction: column;
	height: 100vh;
	width: 100% !important;
	max-width: none !important;
	// 完全透明背景，让流动背景透出来
	background: transparent;
	// 移除毛玻璃效果，让背景完全透明
	backdrop-filter: none;
	border: none;
	box-shadow: none;
	border-radius: 0;
	overflow: hidden;
	// 继承page-container的一些基本样式，但不需要padding和margin
	padding: 0;
	margin: 0;
}

/* 聊天头部 - 现代化优化样式 */
.chat-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 18px 24px;
	background: rgba(255, 255, 255, 0.12);
	backdrop-filter: blur(32px);
	border-bottom: 1px solid rgba(255, 255, 255, 0.15);
	position: sticky;
	top: 0;
	z-index: 100;
	box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.15);
	transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
	min-height: 80px;

	// 添加微妙的渐变边框
	&::after {
		content: '';
		position: absolute;
		bottom: 0;
		left: 5%;
		right: 5%;
		height: 1px;
		background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
	}

	// 滚动时的样式变化
	&.scrolled {
		background: rgba(255, 255, 255, 0.18);
		backdrop-filter: blur(40px);
		box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.2);
	}

	@media (max-width: 768px) {
		padding: 14px 16px;
		background: rgba(255, 255, 255, 0.08);
		backdrop-filter: blur(20px);
		position: fixed;
		width: 100%;
		top: 0;
		left: 0;
		right: 0;
		z-index: 1000;
		box-shadow: 0 2px 16px rgba(0, 0, 0, 0.06), inset 0 1px 0 rgba(255, 255, 255, 0.1);
		flex-shrink: 0;
		min-height: 64px;

		&::after {
			left: 0;
			right: 0;
		}
	}
}

.robot-info {
	display: flex;
	align-items: center;
	gap: 14px;
	transition: all 0.3s ease;

	.ant-avatar {
		border: 2px solid rgba(255, 255, 255, 0.2);
		box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
		transition: all 0.3s ease;

		&:hover {
			border-color: rgba(255, 255, 255, 0.4);
			transform: scale(1.05);
		}
	}
}

.robot-details {
	flex: 1;
	min-width: 0;

	.robot-name {
		font-size: 17px;
		font-weight: 600;
		margin: 0 0 4px 0;
		color: #ffffff;
		text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3), 0 1px 2px rgba(0, 0, 0, 0.2);
		letter-spacing: -0.01em;
		line-height: 1.2;
		white-space: nowrap;
		overflow: hidden;
		text-overflow: ellipsis;

		@media (max-width: 768px) {
			font-size: 15px;
		}
	}

	.robot-status {
		font-size: 13px;
		margin: 0;
		display: flex;
		align-items: center;
		gap: 7px;
		color: rgba(255, 255, 255, 0.8);
		text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4), 0 1px 1px rgba(0, 0, 0, 0.2);

		@media (max-width: 768px) {
			font-size: 12px;
			gap: 6px;
		}
	}
}

.status-indicator {
	width: 9px;
	height: 9px;
	border-radius: 50%;
	background: #52c41a;
	box-shadow: 0 0 8px rgba(82, 196, 26, 0.3);
	position: relative;

	&::before {
		content: '';
		position: absolute;
		inset: -2px;
		border-radius: 50%;
		background: rgba(82, 196, 26, 0.2);
		animation: pulse 2s ease-in-out infinite;
	}

	&.online {
		background: #52c41a;
		box-shadow: 0 0 8px rgba(82, 196, 26, 0.4);
	}

	&.offline {
		background: #ccc;
		box-shadow: 0 0 8px rgba(204, 204, 204, 0.3);

		&::before {
			background: rgba(204, 204, 204, 0.2);
		}
	}
}

@keyframes pulse {
	0%,
	100% {
		opacity: 1;
		transform: scale(1);
	}
	50% {
		opacity: 0.7;
		transform: scale(1.2);
	}
}

.chat-actions {
	display: flex;
	align-items: center;
	gap: 8px;

	.ant-btn {
		color: rgba(255, 255, 255, 0.9);
		border: 1px solid rgba(255, 255, 255, 0.2);
		background: rgba(255, 255, 255, 0.1);
		font-size: 14px;
		padding: 10px 16px;
		border-radius: 10px;
		transition: all 0.3s ease;
		backdrop-filter: blur(8px);
		height: auto;
		min-height: 40px;
		text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 1px 1px rgba(0, 0, 0, 0.2);

		&:hover {
			color: #ffffff;
			background: rgba(255, 255, 255, 0.2);
			border-color: rgba(255, 255, 255, 0.3);
			transform: translateY(-1px);
			box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
			text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4), 0 1px 1px rgba(0, 0, 0, 0.2);
		}

		&:focus {
			color: #ffffff;
			background: rgba(255, 255, 255, 0.15);
			border-color: rgba(255, 255, 255, 0.3);
			text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4), 0 1px 1px rgba(0, 0, 0, 0.2);
		}

		@media (max-width: 768px) {
			padding: 8px 12px;
			font-size: 13px;
			min-height: 36px;
			border-radius: 8px;
		}
	}

	.settings-btn {
		display: flex;
		align-items: center;
		gap: 6px;
	}
}

/* 聊天内容区域 - 透明背景 */
.chat-container {
	flex: 1;
	overflow-y: auto;
	padding: 0;
	// 完全透明的背景，让渐变背景透出来
	background: transparent;
	position: relative;

	@media (max-width: 768px) {
		// 移动端为固定头部留出空间
		padding-top: 70px;
	}
}

.chat-content {
	max-width: 1100px;
	margin: 0 auto;
	padding: 20px;
}

.welcome-message {
	text-align: center;
	padding: 32px 24px;
	margin: 20px auto 24px;
	max-width: 600px;
	// 更现代的毛玻璃卡片效果
	background: rgba(255, 255, 255, 0.15);
	backdrop-filter: blur(20px);
	border-radius: 20px;
	border: 1px solid rgba(255, 255, 255, 0.25);
	box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.2);
	transition: all 0.3s ease;
	position: relative;
	overflow: hidden;

	// 添加微妙的渐变遮罩
	&::before {
		content: '';
		position: absolute;
		top: 0;
		left: 0;
		right: 0;
		height: 1px;
		background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
	}

	&:hover {
		transform: translateY(-2px);
		box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.3);
		border-color: rgba(255, 255, 255, 0.3);
	}

	.ant-avatar {
		margin-bottom: 16px;
		border: 3px solid rgba(255, 255, 255, 0.3);
		box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
		transition: all 0.3s ease;
	}

	h3 {
		font-size: 20px;
		font-weight: 600;
		color: #ffffff;
		text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3), 0 1px 2px rgba(0, 0, 0, 0.2);
		margin: 0 0 12px 0;
		letter-spacing: -0.02em;
		line-height: 1.3;
	}

	p {
		font-size: 15px;
		color: rgba(255, 255, 255, 0.9);
		text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4), 0 1px 1px rgba(0, 0, 0, 0.2);
		margin: 0;
		line-height: 1.6;
		opacity: 1;
	}
}

.messages-list {
	display: flex;
	flex-direction: column;
	gap: 26px; // 进一步缩小间距，让对话更加紧凑，同时保证功能按钮正常显示
}

.message-item {
	display: flex;
	gap: 12px;
	// AI消息容器对齐方式
	align-items: flex-end;
	margin: 0 4px 10px 4px;

	&.user {
		// 用户消息没有头像，直接右对齐内容
		justify-content: flex-end;
		align-items: flex-start;
	}
}

.message-avatar {
	flex-shrink: 0;
	// AI头像对齐到消息底部，与气泡底边对齐
	align-self: flex-end;
}

.message-content {
	flex: 0 1 auto; // 改为自适应宽度，不强制占满空间
	max-width: 70%;
	position: relative; // 为绝对定位的功能按钮提供定位上下文

	.user & {
		display: flex;
		flex-direction: column;
		align-items: flex-end;
	}
}

.message-bubble {
	margin: 8px 0 0 0; // 大幅减少上边距，让对话更紧凑
	padding: 12px 16px;
	border-radius: 18px;
	word-wrap: break-word;
	line-height: 1.5;
	// 增强消息气泡的视觉效果
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);

	&.bot {
		// AI消息使用半透明白色背景和毛玻璃效果
		background: rgba(255, 255, 255, 0.9);
		backdrop-filter: blur(8px);
		border: 1px solid rgba(255, 255, 255, 0.3);
		color: #2c2c2c;
		border-bottom-left-radius: 4px;
	}

	&.user {
		// 用户消息保持渐变背景但增加透明度
		background: linear-gradient(135deg, rgba(102, 126, 234, 0.9) 0%, rgba(118, 75, 162, 0.9) 100%);
		backdrop-filter: blur(8px);
		color: rgb(240, 240, 240);
		border-bottom-right-radius: 4px;
		border: 1px solid rgba(255, 255, 255, 0.2);
	}
}

.message-text {
	margin: 0;
	font-size: 14px;
}

.message-time {
	font-size: 12px;
	color: #e8e8e8;
	padding: 2px 4px;
	margin-bottom: 4px; // 减少下边距，让对话更紧凑
}

/* 移除旧的typing指示器样式，现在使用内联加载样式 */

/* 输入区域 - 透明背景 */
.chat-input {
	padding: 16px 24px;
	// 使用半透明背景和毛玻璃效果
	background: rgba(255, 255, 255, 0.1);
	backdrop-filter: blur(10px);
	border-top: 1px solid rgba(255, 255, 255, 0.2);
	position: relative;
	z-index: 2;
}

.input-container {
	display: flex;
	align-items: flex-end;
	gap: 8px;
	max-width: 800px;
	margin: 0 auto;
}

.message-input {
	flex: 1;
	border-radius: 20px;
	// 输入框使用半透明背景
	background: rgba(255, 255, 255, 0.9);
	backdrop-filter: blur(8px);
	border: 1px solid rgba(255, 255, 255, 0.3);
	padding: 8px 16px;

	:deep(.ant-input) {
		border: none;
		padding: 4px 0;
		font-size: 14px;
		line-height: 1.5;
		background: transparent;

		&:focus {
			box-shadow: none;
		}

		&::placeholder {
			color: rgba(0, 0, 0, 0.5);
		}
	}

	&:focus-within {
		border-color: rgba(102, 126, 234, 0.8);
		box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.2);
		background: rgba(255, 255, 255, 0.95);
	}
}

.emoji-btn {
	color: #666;
	border: none;
	padding: 8px;
	border-radius: 50%;

	&:hover {
		color: #333;
		background: #f5f5f5;
	}
}

.send-btn {
	background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
	border: none;
	border-radius: 50%;
	width: 36px;
	height: 36px;
	display: flex;
	align-items: center;
	justify-content: center;

	&:hover {
		background: linear-gradient(135deg, #5a6fd8 0%, #6a4190 100%);
		transform: translateY(-1px);
	}

	&:disabled {
		background: #d9d9d9;
		transform: none;
	}

	.anticon {
		font-size: 16px;
	}
}

/* 响应式设计 */
@media (max-width: 768px) {
	.chat-page {
		border-radius: 0;
		// 移动端页面容器优化
		position: relative;
		overflow: hidden;
	}

	// chat-header样式已在上面统一定义，移除重复

	.robot-details .robot-name {
		font-size: 14px;
	}

	.chat-content {
		padding: 12px;
		// 确保有足够的边距防止内容溢出
	}

	.welcome-message {
		padding: 20px 16px;
		margin: 16px 8px 20px;
		border-radius: 16px;
		max-width: none;

		h3 {
			font-size: 18px;
			margin-bottom: 10px;
			color: #ffffff;
			text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4), 0 1px 2px rgba(0, 0, 0, 0.2);
		}

		p {
			font-size: 14px;
			line-height: 1.5;
			color: rgba(255, 255, 255, 0.9);
			text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 1px 1px rgba(0, 0, 0, 0.2);
		}

		.ant-avatar {
			margin-bottom: 12px;
			border-width: 2px;
		}

		&:hover {
			transform: none; // 移动端禁用hover效果
		}
	}

	// 移动端消息列表间距优化
	.messages-list {
		gap: 16px; // 移动端更紧凑的间距，最大化屏幕利用率
	}

	// 移动端消息项布局优化
	.message-item {
		margin: 0 4px 10px 4px;

		&.user {
			// 用户消息容器右侧留出更多边距
			margin-right: 8px;
		}
	}

	.message-content {
		// 移动端消息内容更保守的最大宽度
		max-width: 75%;
		position: relative; // 为绝对定位的功能按钮提供定位上下文

		.user & {
			// 用户消息内容进一步限制宽度，防止溢出
			max-width: 70%;
		}
	}

	.message-bubble {
		padding: 10px 14px;
		font-size: 13px;
		// 确保长文本能够换行
		word-break: break-word;
		overflow-wrap: break-word;
	}

	.chat-input {
		padding: 12px 16px;
	}

	.input-container,
	.mobile-input-container {
		gap: 6px;
	}

	.voice-record-bar {
		min-width: 200px;
		min-height: 44px;
	}
}

/* 输入容器包装器 */
.input-wrapper {
	flex: 1;
	display: flex;
	align-items: flex-end;
}

/* ==================== 动画效果 ==================== */

@keyframes successPulse {
	0% {
		transform: scale(1);
	}
	50% {
		transform: scale(1.15);
	}
	100% {
		transform: scale(1);
	}
}

@keyframes checkmarkAppear {
	0% {
		opacity: 0;
		transform: translate(-50%, -50%) scale(0.5);
	}
	100% {
		opacity: 1;
		transform: translate(-50%, -50%) scale(1);
	}
}

/* ==================== 设置菜单样式 ==================== */
.settings-btn {
	color: rgba(255, 255, 255, 0.8);
	border: none;
	transition: all 0.3s ease;

	&:hover {
		color: white;
		background: rgba(255, 255, 255, 0.1);
		// 移除过于明显的旋转效果，改为轻微缩放提升用户体验
		transform: scale(1.05);
	}
}

.settings-menu {
	min-width: 280px;
	background: rgba(255, 255, 255, 0.95);
	backdrop-filter: blur(20px);
	border-radius: 12px;
	box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
	border: 1px solid rgba(255, 255, 255, 0.2);
	padding: 8px 0;

	:deep(.ant-menu-item) {
		border-radius: 8px;
		margin: 2px 8px;
		padding: 0;

		&:hover {
			background: rgba(102, 126, 234, 0.1);
		}
	}
}

.setting-item {
	.setting-content {
		display: flex;
		align-items: center;
		justify-content: space-between;
		width: 100%;
		padding: 12px 16px;
	}

	.setting-info {
		display: flex;
		align-items: flex-start;
		flex: 1;
	}

	.setting-text {
		flex: 1;

		.setting-title {
			font-size: 15px;
			font-weight: 600;
			color: #1a1a1a;
			margin-bottom: 3px;
			letter-spacing: 0.1px;
		}

		.setting-desc {
			font-size: 12px;
			color: #6b7280;
			line-height: 1.5;
			opacity: 0.9;
		}
	}

	:deep(.ant-switch) {
		background-color: #d9d9d9;

		&.ant-switch-checked {
			background-color: #667eea;
		}
	}
}

.action-item {
	display: flex;
	align-items: center;
	padding: 14px 16px;

	.action-text {
		color: #1a1a1a;
		font-weight: 500;
		font-size: 14px;
		letter-spacing: 0.1px;
	}

	&:hover {
		.action-text {
			color: #5a6fd8;
		}
	}
}

/* ==================== 消息状态样式 ==================== */
.message-bubble {
	position: relative;

	&.error {
		background: rgba(255, 77, 79, 0.1) !important;
		border-color: #ff4d4f;

		.message-text {
			color: #ff4d4f;
		}
	}

	&.streaming {
		.message-text {
			position: relative;
		}
	}
}

/* 移除旧的streaming样式，现在使用inline-loading */

/* ==================== 响应式优化 ==================== */
@media (max-width: 768px) {
	.settings-menu {
		min-width: 280px;

		.setting-content {
			padding: 12px 14px;
		}

		.setting-text .setting-title {
			font-size: 14px;
			font-weight: 500;
		}

		.setting-text .setting-desc {
			font-size: 11px;
			opacity: 0.8;
		}

		.action-item {
			padding: 12px 14px;

			.action-text {
				font-size: 13px;
			}
		}
	}

	.chat-actions {
		.settings-btn {
			&:hover {
				transform: none; // 移动端禁用hover动画，避免触屏设备的体验问题
			}
		}
	}
}

/* ==================== 加载状态优化 ==================== */
.send-btn {
	:deep(.ant-btn-loading-icon) {
		margin-right: 0;
	}

	&.ant-btn-loading {
		.anticon-send {
			display: none;
		}
	}
}

/* ==================== 新加载动画样式 ==================== */
.inline-loading {
	display: inline-flex;
	align-items: center;
	margin-left: 4px;
}

.loading-dots {
	display: inline-flex;
	align-items: center;
	gap: 2px;

	.dot {
		width: 4px;
		height: 4px;
		background: currentColor;
		border-radius: 50%;
		opacity: 0.4;
		animation: loadingPulse 1.5s ease-in-out infinite;

		&:nth-child(1) {
			animation-delay: 0s;
		}
		&:nth-child(2) {
			animation-delay: 0.2s;
		}
		&:nth-child(3) {
			animation-delay: 0.4s;
		}
	}
}

@keyframes loadingPulse {
	0%,
	80%,
	100% {
		opacity: 0.4;
		transform: scale(1);
	}
	40% {
		opacity: 1;
		transform: scale(1.2);
	}
}

.empty-message-placeholder {
	display: flex;
	align-items: center;
	min-height: 20px;
	color: #999;
	font-style: italic;
}

@keyframes loadingPulse {
	0%,
	100% {
		opacity: 0.4;
		transform: scale(1);
	}
	50% {
		opacity: 1;
		transform: scale(1.2);
	}
}

/* ==================== 复制按钮样式 ==================== */
.message-bubble {
	position: relative;
	transition: all 0.2s ease;

	&:hover {
		box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
	}
}

/* ==================== 消息功能按钮组 ==================== */
.message-actions {
	position: absolute;
	bottom: -36px;
	right: 4px;
	display: flex;
	align-items: center;
	gap: 6px;
	opacity: 0;
	animation: fadeInActions 0.2s ease forwards;

	// 用户消息的功能按钮定位到右上角
	.user .message-content & {
		top: -36px; // 距离消息气泡顶部8px
		bottom: auto; // 取消底部定位
		right: 8px; // 距离右边缘8px
	}
	z-index: 10;
}

.action-button {
	color: rgb(22, 22, 22);
	display: flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	background: rgba(255, 255, 255, 0.9);
	border: 1px solid rgba(0, 0, 0, 0.08);
	border-radius: 8px;
	cursor: pointer;
	transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
	backdrop-filter: blur(8px);
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 1px 3px rgba(0, 0, 0, 0.04);

	svg {
		width: 14px;
		height: 14px;
		opacity: 0.7;
		transition: all 0.2s ease;
	}

	&:hover {
		background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
		border-color: #667eea;
		color: rgb(31, 31, 31);
		transform: translateY(-1px);
		box-shadow: 0 4px 12px rgba(102, 126, 234, 0.2), 0 2px 6px rgba(102, 126, 234, 0.1);

		svg {
			opacity: 1;
			color: white;
		}
	}

	&:active {
		transform: translateY(0);
	}
}

.response-time {
	padding: 2px 6px;
	background: rgba(0, 0, 0, 0.05);
	border-radius: 4px;
	font-size: 11px;
	color: #666;
	white-space: nowrap;
}

@keyframes fadeInActions {
	from {
		opacity: 0;
		transform: translateY(4px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

/* ==================== 加载动画 ==================== */
.message-loading {
	padding: 16px;
}

.loading-animation {
	display: flex;
	align-items: center;
	gap: 12px;
}

.typing-dots {
	display: flex;
	align-items: center;
	gap: 4px;
}

.typing-dot {
	width: 8px;
	height: 8px;
	background: #667eea;
	border-radius: 50%;
	animation: typingPulse 1.5s infinite;

	&:nth-child(1) {
		animation-delay: 0s;
	}

	&:nth-child(2) {
		animation-delay: 0.2s;
	}

	&:nth-child(3) {
		animation-delay: 0.4s;
	}
}

.loading-text {
	color: #666;
	font-size: 14px;
	font-style: italic;
}

@keyframes typingPulse {
	0%,
	60%,
	100% {
		transform: scale(1);
		opacity: 0.5;
	}
	30% {
		transform: scale(1.2);
		opacity: 1;
	}
}

/* ==================== 代码块头部优化 ==================== */
.copy-dropdown {
	position: absolute;
	top: 6px;
	right: 8px;
	z-index: 10;
}

.copy-button {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 3px;
	min-width: 42px;
	height: 30px;
	padding: 0 6px;
	background: linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(248, 249, 250, 0.9) 100%);
	color: #495057;
	border: 1px solid rgba(0, 0, 0, 0.08);
	border-radius: 10px;
	cursor: pointer;
	transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
	opacity: 0;
	backdrop-filter: blur(12px);
	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08), 0 1px 4px rgba(0, 0, 0, 0.04), inset 0 1px 0 rgba(255, 255, 255, 0.6);
	animation: slideInCopy 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
	position: relative;

	// 高光效果
	&::before {
		content: '';
		position: absolute;
		top: 1px;
		left: 1px;
		right: 1px;
		height: 40%;
		background: linear-gradient(180deg, rgba(255, 255, 255, 0.8) 0%, rgba(255, 255, 255, 0.2) 100%);
		border-radius: 8px 8px 4px 4px;
		pointer-events: none;
	}

	.dropdown-arrow {
		transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
		opacity: 0.6;
		margin-left: 1px;
	}

	&:hover {
		background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
		border-color: rgba(102, 126, 234, 0.3);
		color: white;
		transform: translateY(-2px) scale(1.02);
		box-shadow: 0 8px 25px rgba(102, 126, 234, 0.25), 0 4px 12px rgba(102, 126, 234, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.3);

		&::before {
			background: linear-gradient(180deg, rgba(255, 255, 255, 0.4) 0%, rgba(255, 255, 255, 0.1) 100%);
		}

		.dropdown-arrow {
			opacity: 0.9;
			transform: rotate(180deg) scale(1.1);
		}

		svg:first-child {
			transform: scale(1.05);
		}
	}

	&:active {
		transform: translateY(-1px) scale(0.98);
		box-shadow: 0 4px 12px rgba(102, 126, 234, 0.2), 0 2px 6px rgba(102, 126, 234, 0.1);
	}

	svg {
		width: 14px;
		height: 14px;
		opacity: 0.8;
		transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
		flex-shrink: 0;
	}

	&:hover svg {
		opacity: 1;
	}
}

.copy-menu-item {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 4px 0;
	font-size: 13px;
	color: #495057;
	transition: all 0.2s ease;

	svg {
		opacity: 0.7;
		transition: opacity 0.2s ease;
	}

	&:hover svg {
		opacity: 1;
	}
}

/* 自定义下拉菜单样式 */
:deep(.ant-dropdown-menu) {
	border-radius: 12px;
	box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), 0 4px 16px rgba(0, 0, 0, 0.08), 0 1px 4px rgba(0, 0, 0, 0.04);
	border: 1px solid rgba(0, 0, 0, 0.06);
	overflow: hidden;
	backdrop-filter: blur(12px);
	background: linear-gradient(135deg, rgba(255, 255, 255, 0.98) 0%, rgba(248, 249, 250, 0.95) 100%);
	min-width: 140px;

	&::before {
		content: '';
		position: absolute;
		top: 0;
		left: 0;
		right: 0;
		height: 1px;
		background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.8) 50%, transparent 100%);
	}
}

:deep(.ant-dropdown-menu-item) {
	padding: 12px 16px;
	transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
	position: relative;
	border-radius: 0;

	&:first-child {
		border-radius: 11px 11px 0 0;
	}

	&:last-child {
		border-radius: 0 0 11px 11px;
	}

	&:only-child {
		border-radius: 11px;
	}

	&::after {
		content: '';
		position: absolute;
		bottom: 0;
		left: 16px;
		right: 16px;
		height: 1px;
		background: linear-gradient(90deg, transparent 0%, rgba(0, 0, 0, 0.04) 50%, transparent 100%);
	}

	&:last-child::after {
		display: none;
	}

	&:hover {
		background: linear-gradient(135deg, rgba(102, 126, 234, 0.08) 0%, rgba(118, 75, 162, 0.08) 100%);
		color: #667eea;
		transform: translateX(2px);

		&::after {
			background: linear-gradient(90deg, transparent 0%, rgba(102, 126, 234, 0.1) 50%, transparent 100%);
		}
	}

	&:active {
		background: linear-gradient(135deg, rgba(102, 126, 234, 0.15) 0%, rgba(118, 75, 162, 0.15) 100%);
		color: #5a6bc7;
		transform: translateX(1px) scale(0.98);
	}
}

@keyframes slideInCopy {
	0% {
		opacity: 0;
		transform: translateX(8px) translateY(-2px) scale(0.9);
	}
	50% {
		opacity: 0.8;
		transform: translateX(-1px) translateY(-1px) scale(0.95);
	}
	100% {
		opacity: 1;
		transform: translateX(0) translateY(0) scale(1);
	}
}

@keyframes fadeInCopy {
	from {
		opacity: 0;
		transform: translateY(-4px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

/* ==================== Markdown样式 ==================== */
.message-text {
	line-height: 1.6;

	// 确保HTML内容的基本样式
	:deep(strong) {
		font-weight: 600;
		color: inherit;
	}

	:deep(em) {
		font-style: italic;
		color: inherit;
	}

	:deep(a) {
		color: #667eea;
		text-decoration: underline;

		&:hover {
			color: #5a6fd8;
		}
	}

	:deep(br) {
		line-height: 1.8;
	}
}

.inline-code {
	background: rgba(102, 126, 234, 0.1);
	color: #667eea;
	padding: 2px 6px;
	border-radius: 4px;
	font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
	font-size: 0.9em;
	font-weight: 500;
}

/* ==================== 代码块样式 ==================== */
.code-block {
	margin: 16px 0;
	border-radius: 12px;
	overflow: hidden;
	background: linear-gradient(135deg, #fafbfc 0%, #f6f8fa 100%);
	border: 1px solid #e1e4e8;
	max-width: 100%;
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04), 0 1px 3px rgba(0, 0, 0, 0.06);
	position: relative;
	display: block;
	clear: both;
	transition: all 0.2s ease;
	font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

	&:hover {
		box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06), 0 2px 6px rgba(0, 0, 0, 0.08);
		transform: translateY(-1px);
	}
}

/* ==================== 响应式优化 ==================== */
@media (max-width: 768px) {
	.message-actions {
		gap: 4px;
		// 用户消息的功能按钮在移动端定位到右上角
		.user .message-content & {
			top: 6px; // 移动端距离消息气泡顶部6px
			bottom: auto; // 取消底部定位
			right: 6px; // 移动端距离右边缘6px
		}
	}

	.action-button {
		// outline: 1px solid red;
		width: 32px;
		height: 32px;
		border-radius: 10px;

		svg {
			width: 15px;
			height: 15px;
		}

		&:hover {
			transform: none; // 移动端禁用hover动画
		}

		&:active {
			transform: scale(0.94);
		}
	}

	.response-time {
		font-size: 10px;
		padding: 1px 4px;
	}

	.copy-button {
		min-width: 46px;
		height: 34px;
		gap: 3px;
		padding: 0 8px;
		border-radius: 12px;
		background: linear-gradient(135deg, rgba(255, 255, 255, 0.96) 0%, rgba(248, 249, 250, 0.92) 100%);
		box-shadow: 0 3px 16px rgba(0, 0, 0, 0.1), 0 2px 6px rgba(0, 0, 0, 0.06), inset 0 1px 0 rgba(255, 255, 255, 0.7);

		svg {
			width: 15px;
			height: 15px;
		}

		.dropdown-arrow {
			width: 13px;
			height: 13px;
		}

		// 移动端使用touch反馈替代hover
		&:hover {
			transform: none;
			background: linear-gradient(135deg, rgba(255, 255, 255, 0.96) 0%, rgba(248, 249, 250, 0.92) 100%);
			color: #495057;
			box-shadow: 0 3px 16px rgba(0, 0, 0, 0.1), 0 2px 6px rgba(0, 0, 0, 0.06), inset 0 1px 0 rgba(255, 255, 255, 0.7);

			&::before {
				background: linear-gradient(180deg, rgba(255, 255, 255, 0.8) 0%, rgba(255, 255, 255, 0.2) 100%);
			}

			.dropdown-arrow {
				transform: none;
			}
		}

		// 移动端触摸反馈
		&:active {
			transform: scale(0.96);
			background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
			color: white;
			box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3), 0 1px 4px rgba(102, 126, 234, 0.2);
		}
	}

	.copy-dropdown {
		top: 6px;
		right: 6px;
	}

	.code-block {
		margin: 12px 0;
		border-radius: 10px;
		box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08), 0 1px 4px rgba(0, 0, 0, 0.05);

		&:hover {
			transform: none; // 移动端禁用hover动画
		}

		.code-header {
			padding: 10px 14px;
			min-height: 40px;

			.code-lang {
				font-size: 11px;
				padding: 3px 8px;

				&::before {
					width: 6px;
					height: 6px;
					margin-right: 4px;
				}
			}
		}

		pre {
			padding: 16px;
			font-size: 13px;
			line-height: 1.6;
			overflow-x: scroll;
			-webkit-overflow-scrolling: touch;
		}

		code {
			font-size: 13px !important;
			font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;
		}
	}

	.copy-code-btn {
		padding: 7px 10px;
		font-size: 10px;
		gap: 4px;
		border-radius: 5px;
		min-width: 60px;
		justify-content: center;
		min-height: 28px;
		box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.05);

		// 移动端禁用hover效果，使用active效果
		&:hover {
			transform: none;
		}

		&:active {
			transform: scale(0.95);
			background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
			color: white;
		}

		&.copied {
			transform: scale(1.02);
		}

		svg {
			width: 11px;
			height: 11px;
		}
	}

	.inline-code {
		font-size: 0.85em;
	}
}

/* 登录提示Modal样式 */
.login-prompt-modal {
	:deep(.ant-modal-content) {
		background: rgba(255, 255, 255, 0.15);
		backdrop-filter: blur(24px);
		border: 1px solid rgba(255, 255, 255, 0.3);
		border-radius: 20px;
		overflow: hidden;
	}

	:deep(.ant-modal-header) {
		background: transparent;
		border-bottom: 1px solid rgba(255, 255, 255, 0.2);
		padding: 24px 24px 16px;

		.ant-modal-title {
			color: rgba(255, 255, 255, 0.9);
			font-size: 18px;
			font-weight: 600;
			text-align: center;
		}
	}

	:deep(.ant-modal-body) {
		padding: 20px 24px 24px;
	}
}

.login-prompt-content {
	text-align: center;

	.prompt-icon {
		font-size: 48px;
		margin-bottom: 16px;
	}

	.prompt-title {
		font-size: 20px;
		font-weight: 600;
		color: rgba(255, 255, 255, 0.9);
		margin: 0 0 12px 0;
	}

	.prompt-description {
		font-size: 14px;
		color: rgba(255, 255, 255, 0.8);
		line-height: 1.6;
		margin: 0 0 24px 0;
	}

	.prompt-actions {
		display: flex;
		gap: 12px;
		margin-bottom: 16px;

		.login-btn {
			flex: 1;
			height: 44px;
			border-radius: 12px;
			font-size: 15px;
			font-weight: 600;
			background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
			border: none;
			transition: all 0.3s ease;

			&:hover {
				background: linear-gradient(135deg, #5a6fd8 0%, #6a4190 100%);
				transform: translateY(-2px);
				box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3);
			}
		}

		.register-btn {
			flex: 1;
			height: 44px;
			border-radius: 12px;
			font-size: 15px;
			font-weight: 500;
			background: rgba(255, 255, 255, 0.1);
			border: 1px solid rgba(255, 255, 255, 0.3);
			color: rgba(255, 255, 255, 0.9);
			transition: all 0.3s ease;

			&:hover {
				background: rgba(255, 255, 255, 0.2);
				border-color: rgba(255, 255, 255, 0.4);
				transform: translateY(-2px);
			}
		}
	}

	.prompt-footer {
		.close-btn {
			color: rgba(255, 255, 255, 0.6);
			font-size: 13px;
			transition: color 0.3s ease;

			&:hover {
				color: rgba(255, 255, 255, 0.8);
			}
		}
	}
}

/* 游客体验公告样式 */
.guest-notice-popup {
	position: fixed !important;
	top: 20px !important;
	right: 20px !important;
	bottom: auto !important;
	left: auto !important;
	width: 320px;
	background: rgba(255, 255, 255, 0.95);
	backdrop-filter: blur(12px);
	border-radius: 12px;
	box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
	z-index: 9999 !important;
	border: 1px solid rgba(255, 255, 255, 0.3);
	animation: slideInRight 0.3s ease-out;

	.notice-header {
		display: flex;
		align-items: center;
		padding: 16px 16px 12px;
		border-bottom: 1px solid rgba(0, 0, 0, 0.1);

		.notice-icon {
			margin-right: 8px;
			color: #ff6b35;
			display: flex;
			align-items: center;
			justify-content: center;
		}

		.notice-title {
			flex: 1;
			font-size: 14px;
			font-weight: 600;
			color: #333;
		}

		.close-btn {
			background: none;
			border: none;
			font-size: 20px;
			color: #666;
			cursor: pointer;
			padding: 0;
			width: 24px;
			height: 24px;
			display: flex;
			align-items: center;
			justify-content: center;
			border-radius: 4px;
			transition: all 0.2s ease;

			&:hover {
				background: rgba(0, 0, 0, 0.1);
				color: #333;
			}
		}
	}

	.notice-content {
		padding: 12px 16px 16px;

		p {
			margin: 0 0 8px;
			font-size: 13px;
			color: #666;
			line-height: 1.4;

			&:last-of-type {
				margin-bottom: 12px;
			}

			strong {
				color: #ff6b35;
				font-weight: 600;
			}
		}

		.notice-actions {
			display: flex;
			gap: 8px;

			button {
				flex: 1;
				padding: 8px 12px;
				border: none;
				border-radius: 6px;
				font-size: 12px;
				cursor: pointer;
				transition: all 0.2s ease;

				&.login-btn {
					background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
					color: white;

					&:hover {
						transform: translateY(-1px);
						box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
					}
				}

				&.register-btn {
					background: rgba(102, 126, 234, 0.1);
					color: #667eea;
					border: 1px solid rgba(102, 126, 234, 0.3);

					&:hover {
						background: rgba(102, 126, 234, 0.2);
					}
				}
			}
		}
	}
}

@keyframes slideInRight {
	from {
		transform: translateX(100%);
		opacity: 0;
	}
	to {
		transform: translateX(0);
		opacity: 1;
	}
}

/* 移动端适配 (平板到大手机) */
@media (max-width: 768px) {
	.guest-notice-popup {
		top: 20px !important;
		right: 20px !important;
		width: 320px !important;
		min-width: 320px !important;
		max-width: 100vw !important;
		border-radius: 12px 12px 16px 16px !important;
		box-shadow: 0 2px 16px rgba(0, 0, 0, 0.12) !important;
		animation: slideInDown 0.3s ease-out !important;
		overflow: visible !important;

		.notice-header {
			padding: 12px 16px 8px;
			min-height: 40px;
			max-height: 40px;
			flex-shrink: 0;

			.notice-icon {
				svg {
					width: 16px;
					height: 16px;
				}
			}

			.notice-title {
				font-size: 14px;
				font-weight: 500;
			}

			.close-btn {
				width: 30px;
				height: 30px;
				font-size: 22px;
				flex-shrink: 0;
			}
		}

		.notice-content {
			padding: 0 16px 12px;
			min-height: 80px;
			max-height: none;
			overflow-y: visible;

			p {
				font-size: 13px;
				margin-bottom: 6px;
				line-height: 1.4;

				&:last-of-type {
					margin-bottom: 8px;
				}

				strong {
					font-size: 14px;
					font-weight: 600;
				}
			}

			.notice-actions {
				flex-direction: row;
				gap: 8px;
				flex-shrink: 0;

				button {
					padding: 8px 16px;
					font-size: 12px;
					border-radius: 6px;
					white-space: nowrap;
					min-height: 32px;
					flex: 1;
				}
			}
		}
	}
}

/* 超小屏幕优化 (小手机) */
@media (max-width: 375px) {
	.guest-notice-popup {
		left: 10px !important;
		right: 10px !important;
		width: auto !important;
		min-width: auto !important;
		max-width: none !important;
		max-height: none !important;
		border-radius: 10px 10px 12px 12px !important;

		.notice-header {
			padding: 10px 12px 6px;
			min-height: 32px;
			max-height: 32px;

			.notice-icon {
				svg {
					width: 14px;
					height: 14px;
				}
			}

			.notice-title {
				font-size: 12px;
				font-weight: 500;
			}

			.close-btn {
				width: 26px;
				height: 26px;
				font-size: 20px;
			}
		}

		.notice-content {
			padding: 0 12px 0px;
			min-height: 66px;
			max-height: none;

			p {
				font-size: 12px;
				margin-bottom: 5px;
				line-height: 1.3;

				&:last-of-type {
					margin-bottom: 6px;
				}

				strong {
					font-size: 13px;
					font-weight: 600;
				}
			}

			.notice-actions {
				gap: 6px;

				button {
					padding: 6px 12px;
					font-size: 11px;
					border-radius: 4px;
					min-height: 28px;
					flex: 1;
				}
			}
		}
	}
}

@keyframes slideInDown {
	from {
		transform: translateY(-100%);
		opacity: 0;
	}
	to {
		transform: translateY(0);
		opacity: 1;
	}
}

/* 导入现代化代码块样式 */
@import '../styles/code-block-modern.scss';
</style>

<!-- 全局样式，用于动态生成的代码块 -->
<style lang="scss">
/* 代码块相关样式 - 必须是全局的，因为代码块是动态生成的 */
.code-block {
	position: relative;
	margin: 16px 0;
	border-radius: 8px;
	overflow: hidden;
	background: #ffffff !important;
	border: 1px solid #e5e7eb !important;
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05) !important;

	pre {
		margin: 0 !important;
		padding: 18px 16px 0px 16px !important;
		background: #ffffff !important;
		overflow-x: auto;

		code {
			font-family: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace !important;
			font-size: 14px !important;
			line-height: 1.6 !important;
			color: #1f2937 !important;
		}
	}
}

.code-header-overlay {
	position: absolute !important;
	top: 0 !important;
	right: 0 !important;
	left: 0 !important;
	display: flex !important;
	align-items: center !important;
	justify-content: flex-start !important;
	padding: 12px 16px !important;
	background: linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(248, 250, 252, 0.98) 100%) !important;
	border-bottom: 1px solid rgba(226, 232, 240, 0.8) !important;
	border-top-left-radius: 8px !important;
	border-top-right-radius: 8px !important;
	backdrop-filter: blur(12px) !important;
	z-index: 10 !important;
	transition: all 0.3s ease !important;
}

.code-lang-tag {
	display: inline-flex !important;
	align-items: center !important;
	padding: 6px 12px !important;
	background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
	border: none !important;
	border-radius: 8px !important;
	font-size: 12px !important;
	font-weight: 600 !important;
	color: white !important;
	text-transform: uppercase !important;
	letter-spacing: 0.5px !important;
	font-family: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace !important;
	box-shadow: 0 2px 8px rgba(102, 126, 234, 0.25) !important;
	transition: all 0.3s ease !important;
	position: relative !important;
	overflow: hidden !important;
}

.copy-code-btn {
	display: flex !important;
	align-items: center !important;
	justify-content: center;
	gap: 6px !important;
	background: #e5e7eb !important;
	border: none !important;
	border-radius: 6px !important;
	padding: 8px 12px !important;
	font-size: 12px !important;
	font-weight: 500 !important;
	color: #374151 !important;
	cursor: pointer !important;
	transition: all 0.2s ease !important;
	user-select: none !important;
	position: absolute !important;
	top: 12px !important;
	right: 12px !important;
	min-height: 32px !important;
	min-width: 70px !important;

	.copy-text {
		font-size: 12px !important;
		font-weight: 500 !important;
		transition: all 0.2s ease !important;
	}

	&:hover {
		background: #d1d5db !important;
		transform: translateY(-1px) !important;
		box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1) !important;
	}

	&:active {
		transform: translateY(0) !important;
		box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1) !important;
	}

	&.copied {
		background: #16a34a !important;
		color: white !important;
		transform: translateY(0) !important;
		box-shadow: 0 2px 4px rgba(22, 163, 74, 0.25) !important;

		svg {
			animation: checkmark 0.3s ease-in-out !important;
		}

		.copy-text {
			animation: textPulse 0.3s ease-in-out !important;
		}
	}

	svg {
		transition: transform 0.2s ease !important;
		stroke-width: 2 !important;
		flex-shrink: 0 !important;
		width: 16px !important;
		height: 16px !important;
		display: block !important;
	}
}

@keyframes checkmark {
	0% {
		transform: scale(1);
	}
	50% {
		transform: scale(1.2);
	}
	100% {
		transform: scale(1);
	}
}

@keyframes textPulse {
	0% {
		transform: scale(1);
		opacity: 1;
	}
	50% {
		transform: scale(1.1);
		opacity: 0.8;
	}
	100% {
		transform: scale(1);
		opacity: 1;
	}
}

/* 流式输出相关样式 - 必须是全局的 */
.inline-loading {
	display: inline-flex !important;
	align-items: center !important;
	margin-left: 4px !important;
}

/* 初始加载状态样式 - 与文字高度一致 */
.initial-loading {
	display: flex !important;
	align-items: center !important;
	height: 1.5em !important; /* 与文字行高一致 */
	line-height: 1.5 !important;
}

.loading-dots {
	display: inline-flex !important;
	align-items: center !important;
	gap: 2px !important;

	.dot {
		width: 4px !important;
		height: 4px !important;
		background: currentColor !important;
		border-radius: 50% !important;
		opacity: 0.4 !important;
		animation: loadingPulse 1.5s ease-in-out infinite !important;

		&:nth-child(1) {
			animation-delay: 0s !important;
		}
		&:nth-child(2) {
			animation-delay: 0.2s !important;
		}
		&:nth-child(3) {
			animation-delay: 0.4s !important;
		}
	}
}

@keyframes loadingPulse {
	0%,
	80%,
	100% {
		opacity: 0.4;
		transform: scale(1);
	}
	40% {
		opacity: 1;
		transform: scale(1.2);
	}
}

/* 流式输出状态样式 */
.message-bubble.streaming {
	.message-text {
		position: relative !important;
	}
}

/* 打字机效果样式 */
.typing-dots {
	display: flex !important;
	align-items: center !important;
	gap: 4px !important;
}

.typing-dot {
	width: 8px !important;
	height: 8px !important;
	background: #667eea !important;
	border-radius: 50% !important;
	animation: typingPulse 1.5s infinite !important;

	&:nth-child(1) {
		animation-delay: 0s !important;
	}
	&:nth-child(2) {
		animation-delay: 0.2s !important;
	}
	&:nth-child(3) {
		animation-delay: 0.4s !important;
	}
}

@keyframes typingPulse {
	0%,
	60%,
	100% {
		transform: scale(1);
		opacity: 0.5;
	}
	30% {
		transform: scale(1.2);
		opacity: 1;
	}
}

/* ==================== 电话界面样式 ==================== */
.call-interface {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
	z-index: 9999;
	display: flex;
	align-items: center;
	justify-content: center;
	color: white;
}

.call-content {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
	max-width: 600px;
	padding: 40px;
	text-align: center;
}

.call-header {
	margin-bottom: 60px;
	position: relative;

	.call-title {
		font-size: 24px;
		font-weight: 600;
		margin-bottom: 8px;
	}

	.call-duration {
		font-size: 18px;
		opacity: 0.9;
		margin-bottom: 12px;
		font-family: 'JetBrains Mono', monospace;
	}

	.call-status {
		font-size: 16px;
		opacity: 0.8;
		margin-bottom: 16px;

		.listening {
			color: #4ade80;
			animation: pulse 1.5s infinite;
		}

		.thinking {
			color: #fbbf24;
			animation: pulse 1.5s infinite;
		}

		.speaking {
			color: #fb7185;
			animation: pulse 1.5s infinite;
		}
	}

	.audio-monitor {
		display: flex;
		gap: 20px;
		justify-content: center;
		margin-bottom: 12px;
		font-size: 14px;
		opacity: 0.9;

		> div {
			display: flex;
			flex-direction: column;
			align-items: center;
			gap: 2px;
		}

		.label {
			font-size: 12px;
			opacity: 0.7;
		}

		.value {
			font-family: 'JetBrains Mono', monospace;
			font-weight: 600;

			&.speaking {
				color: #4ade80;
				animation: pulse 1s infinite;
			}
		}
	}

	.audio-settings-btn {
		position: absolute;
		top: 0;
		right: 0;
		background: rgba(255, 255, 255, 0.1);
		border: 1px solid rgba(255, 255, 255, 0.2);
		border-radius: 8px;
		padding: 8px;
		color: white;
		cursor: pointer;
		transition: all 0.3s ease;

		&:hover {
			background: rgba(255, 255, 255, 0.2);
			transform: scale(1.1);
		}
	}
}

/* 音频设置面板 */
.audio-settings-panel {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background: rgba(0, 0, 0, 0.8);
	backdrop-filter: blur(10px);
	display: flex;
	align-items: center;
	justify-content: center;
	z-index: 10;
}

.settings-content {
	background: rgba(255, 255, 255, 0.95);
	color: #333;
	border-radius: 16px;
	padding: 24px;
	max-width: 480px;
	width: 90%;
	max-height: 80vh;
	overflow-y: auto;
}

.settings-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 24px;
	padding-bottom: 16px;
	border-bottom: 1px solid rgba(0, 0, 0, 0.1);

	h3 {
		margin: 0;
		font-size: 20px;
		font-weight: 600;
	}

	.close-btn {
		background: none;
		border: none;
		padding: 8px;
		border-radius: 8px;
		cursor: pointer;
		transition: background 0.3s ease;

		&:hover {
			background: rgba(0, 0, 0, 0.1);
		}
	}
}

.setting-group {
	margin-bottom: 24px;
	padding: 20px;
	background: rgba(0, 0, 0, 0.05);
	border-radius: 12px;

	.setting-title {
		font-size: 16px;
		font-weight: 600;
		margin-bottom: 8px;
		color: #333;
	}

	.setting-description {
		font-size: 14px;
		color: #666;
		margin-bottom: 16px;
		line-height: 1.5;
	}
}

.calibration-controls {
	display: flex;
	flex-direction: column;
	gap: 12px;

	.calibration-info {
		display: flex;
		gap: 16px;
		font-size: 14px;
		color: #666;
		font-family: 'JetBrains Mono', monospace;
		flex-wrap: wrap;

		span {
			background: rgba(0, 0, 0, 0.05);
			padding: 4px 8px;
			border-radius: 4px;
			border: 1px solid rgba(0, 0, 0, 0.1);
		}
	}
}

.threshold-controls,
.silence-controls,
.sensitivity-controls {
	.threshold-slider,
	.silence-controls,
	.sensitivity-slider {
		margin-bottom: 16px;
	}

	label {
		display: block;
		font-size: 14px;
		font-weight: 500;
		margin-bottom: 8px;
		color: #333;
	}

	.slider {
		width: 100%;
		height: 6px;
		border-radius: 3px;
		background: #ddd;
		outline: none;
		margin-bottom: 8px;

		&::-webkit-slider-thumb {
			appearance: none;
			width: 20px;
			height: 20px;
			border-radius: 50%;
			background: #667eea;
			cursor: pointer;
			box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
		}

		&::-moz-range-thumb {
			width: 20px;
			height: 20px;
			border-radius: 50%;
			background: #667eea;
			cursor: pointer;
			border: none;
			box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
		}
	}

	.range-labels {
		display: flex;
		justify-content: space-between;
		font-size: 12px;
		color: #888;
	}

	.threshold-info {
		margin-top: 8px;
		padding: 8px 12px;
		background: rgba(102, 126, 234, 0.05);
		border-radius: 6px;
		font-size: 13px;
		color: #667eea;
		border: 1px solid rgba(102, 126, 234, 0.1);
	}
}

.threshold-presets,
.sensitivity-presets {
	display: flex;
	gap: 8px;
	flex-wrap: wrap;

	.preset-btn {
		background: rgba(102, 126, 234, 0.1);
		border: 1px solid rgba(102, 126, 234, 0.3);
		border-radius: 6px;
		padding: 6px 12px;
		font-size: 12px;
		color: #667eea;
		cursor: pointer;
		transition: all 0.3s ease;

		&:hover {
			background: rgba(102, 126, 234, 0.2);
			border-color: #667eea;
		}
	}
}

/* PC端水波纹球体 */
.wave-sphere {
	margin: 40px 0;
	position: relative;
}

.sphere {
	width: 200px;
	height: 200px;
	border-radius: 50%;
	position: relative;
	background: rgba(255, 255, 255, 0.1);
	backdrop-filter: blur(10px);
	display: flex;
	align-items: center;
	justify-content: center;
	margin: 0 auto;
	transition: all 0.3s ease;

	&.listening {
		background: rgba(74, 222, 128, 0.2);
		box-shadow: 0 0 30px rgba(74, 222, 128, 0.3);
	}

	&.thinking {
		background: rgba(251, 191, 36, 0.2);
		box-shadow: 0 0 30px rgba(251, 191, 36, 0.3);
	}

	&.speaking {
		background: rgba(251, 113, 133, 0.2);
		box-shadow: 0 0 30px rgba(251, 113, 133, 0.3);
		animation: speakingPulse 0.5s ease-in-out infinite alternate;
	}

	&.user-speaking {
		background: rgba(59, 130, 246, 0.3);
		box-shadow: 0 0 40px rgba(59, 130, 246, 0.5);
		animation: userSpeakingPulse 0.3s ease-in-out infinite alternate;
	}
}

.wave {
	position: absolute;
	border-radius: 50%;
	border: 1px solid rgba(255, 255, 255, 0.3);
	animation: waveAnimation 2s linear infinite;

	&.wave1 {
		width: 220px;
		height: 220px;
		top: -10px;
		left: -10px;
		animation-delay: 0s;
	}

	&.wave2 {
		width: 250px;
		height: 250px;
		top: -25px;
		left: -25px;
		animation-delay: 0.7s;
	}

	&.wave3 {
		width: 280px;
		height: 280px;
		top: -40px;
		left: -40px;
		animation-delay: 1.4s;
	}
}

.inner-circle {
	width: 120px;
	height: 120px;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.2);
	display: flex;
	align-items: center;
	justify-content: center;
	backdrop-filter: blur(5px);
}

/* 移动端界面 */
.mobile-visual {
	margin: 40px 0;
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
}

.mobile-icon {
	width: 120px;
	height: 120px;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.1);
	backdrop-filter: blur(10px);
	display: flex;
	align-items: center;
	justify-content: center;
	margin-bottom: 20px;
	transition: all 0.3s ease;

	&.listening {
		background: rgba(74, 222, 128, 0.2);
		box-shadow: 0 0 20px rgba(74, 222, 128, 0.3);
	}

	&.thinking {
		background: rgba(251, 191, 36, 0.2);
		box-shadow: 0 0 20px rgba(251, 191, 36, 0.3);
		animation: rotation 2s linear infinite;
	}

	&.speaking {
		background: rgba(251, 113, 133, 0.2);
		box-shadow: 0 0 20px rgba(251, 113, 133, 0.3);
		animation: mobileSpeakingPulse 0.5s ease-in-out infinite alternate;
	}

	&.user-speaking {
		background: rgba(59, 130, 246, 0.3);
		box-shadow: 0 0 30px rgba(59, 130, 246, 0.5);
		animation: mobileUserSpeakingPulse 0.3s ease-in-out infinite alternate;
	}
}

.mobile-ripple {
	position: absolute;
	top: 0;
	left: 50%;
	transform: translateX(-50%);
}

.ripple {
	position: absolute;
	border: 1px solid rgba(255, 255, 255, 0.3);
	border-radius: 50%;
	animation: rippleAnimation 2s linear infinite;

	&.ripple1 {
		width: 140px;
		height: 140px;
		top: -10px;
		left: -70px;
		animation-delay: 0s;
	}

	&.ripple2 {
		width: 170px;
		height: 170px;
		top: -25px;
		left: -85px;
		animation-delay: 0.7s;
	}

	&.ripple3 {
		width: 200px;
		height: 200px;
		top: -40px;
		left: -100px;
		animation-delay: 1.4s;
	}
}

.call-controls {
	display: flex;
	gap: 20px;
	margin-top: 60px;

	.send-voice-btn,
	.end-call-btn {
		min-width: 120px;
		height: 50px;
		border-radius: 25px;
		font-size: 16px;
		font-weight: 600;
	}

	.send-voice-btn {
		background: rgba(74, 222, 128, 0.9);
		border: none;

		&:hover {
			background: rgba(74, 222, 128, 1);
		}
	}

	.end-call-btn {
		background: rgba(239, 68, 68, 0.9);
		border: none;

		&:hover {
			background: rgba(239, 68, 68, 1);
		}
	}
}

.call-btn {
	color: #667eea !important;

	&:hover {
		color: #764ba2 !important;
		background: rgba(102, 126, 234, 0.1) !important;
	}

	&:disabled {
		opacity: 0.5;
		cursor: not-allowed;
	}
}

/* 动画效果 */
@keyframes waveAnimation {
	0% {
		transform: scale(1);
		opacity: 1;
	}
	100% {
		transform: scale(1.3);
		opacity: 0;
	}
}

@keyframes rippleAnimation {
	0% {
		transform: scale(1);
		opacity: 1;
	}
	100% {
		transform: scale(1.5);
		opacity: 0;
	}
}

@keyframes speakingPulse {
	0% {
		transform: scale(1);
	}
	100% {
		transform: scale(1.05);
	}
}

@keyframes mobileSpeakingPulse {
	0% {
		transform: scale(1);
	}
	100% {
		transform: scale(1.1);
	}
}

@keyframes rotation {
	0% {
		transform: rotate(0deg);
	}
	100% {
		transform: rotate(360deg);
	}
}

@keyframes userSpeakingPulse {
	0% {
		transform: scale(1);
		box-shadow: 0 0 40px rgba(59, 130, 246, 0.5);
	}
	100% {
		transform: scale(1.08);
		box-shadow: 0 0 60px rgba(59, 130, 246, 0.7);
	}
}

@keyframes mobileUserSpeakingPulse {
	0% {
		transform: scale(1);
		box-shadow: 0 0 30px rgba(59, 130, 246, 0.5);
	}
	100% {
		transform: scale(1.12);
		box-shadow: 0 0 45px rgba(59, 130, 246, 0.7);
	}
}

/* 移动端适配 */
.call-interface.mobile {
	.call-content {
		padding: 20px;
	}

	.call-header {
		margin-bottom: 40px;

		.call-title {
			font-size: 20px;
		}

		.call-duration {
			font-size: 16px;
		}

		.call-status {
			font-size: 14px;
		}

		.audio-monitor {
			gap: 12px;
			font-size: 12px;

			.label {
				font-size: 10px;
			}
		}

		.audio-settings-btn {
			top: 10px;
			right: 10px;
			padding: 6px;
		}
	}

	.mobile-visual {
		margin: 20px 0;
	}

	.call-controls {
		margin-top: 40px;
		gap: 15px;

		.send-voice-btn,
		.end-call-btn {
			min-width: 100px;
			height: 45px;
			font-size: 14px;
		}
	}

	.settings-content {
		width: 95%;
		padding: 20px;
		max-height: 85vh;
	}

	.setting-group {
		padding: 16px;
		margin-bottom: 20px;

		.setting-title {
			font-size: 15px;
		}

		.setting-description {
			font-size: 13px;
		}
	}

	.threshold-presets {
		.preset-btn {
			padding: 8px 10px;
			font-size: 11px;
		}
	}
}
</style>
